diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index fe4e633..614fdfe 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -123,6 +123,6 @@ {"id":"ifcurl-vam","title":"Phase 6: Bonsai offer ifc:// URL when saving linked model reference","description":"When saving an IFCDOCUMENTREFERENCE in Bonsai, offer the option to write the location as an ifc:// URL rather than a relative path. When a relative path would traverse above the repository root, prompt the user to convert it to an ifc:// URL. Requires Phase 4 federation (ifcurl-bqt).","status":"deferred","priority":4,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:49:16Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:15:13Z","defer_until":"2026-12-01T00:00:00Z","dependencies":[{"issue_id":"ifcurl-vam","depends_on_id":"ifcurl-bqt","type":"blocks","created_at":"2026-04-23T06:49:23Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0} {"id":"ifcurl-9k2","title":"Phase 5: IFC Viewer integration (equivalent of Phase 4)","description":"Add ifc:// OS protocol handler and 'Copy view URL' button to the IFC Viewer desktop application, equivalent to the Bonsai Phase 4 integration. Depends on Phase 4 being complete as a reference implementation.","status":"deferred","priority":4,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:49:08Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:15:12Z","defer_until":"2026-12-01T00:00:00Z","dependencies":[{"issue_id":"ifcurl-9k2","depends_on_id":"ifcurl-0oj","type":"blocks","created_at":"2026-04-23T06:49:14Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0} {"id":"ifcurl-prc","title":"Phase 3c: 3D diff view for IFC PR merges","description":"After a PR merge completes, surface a 'View merge in 3D' button using the Phase 3b viewer. Use @thatopen/components highlighter to colour added, removed, and modified elements differently, driven by comparing the merged IFC against either parent. Requires Phase 3b viewer (ifcurl-i1s) to be working.","status":"closed","priority":4,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:30Z","created_by":"Bruno Postle","updated_at":"2026-04-26T17:15:07Z","closed_at":"2026-04-26T17:15:07Z","close_reason":"Rendered diff already implemented in footer.tmpl Case 3; static PNG via /render_diff endpoint, not interactive 3D","dependencies":[{"issue_id":"ifcurl-prc","depends_on_id":"ifcurl-i1s","type":"blocks","created_at":"2026-04-23T06:48:36Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0} -{"_type":"memory","key":"ifcurl-service-names-are-ifcurl-api-service-and","value":"ifcurl service names are ifcurl-api.service and ifcurl-render.service (not ifcurl.service). Install path for Python package: /opt/ifcurl/lib/python3.14/site-packages/ifcurl/. Python binary: /opt/ifcurl/bin/python3."} {"_type":"memory","key":"forgejo-build-and-deploy-procedure-go-build-c","value":"Forgejo build and deploy procedure: go build -C /home/bruno/src/forgejo -tags 'sqlite sqlite_unlock_notify' -ldflags \"-X 'forgejo.org/modules/setting.StaticRootPath=/usr/share/forgejo'\" -o /home/bruno/src/forgejo/forgejo . — then sudo cp forgejo /usr/bin/forgejo. StaticRootPath=/usr/share/forgejo. CustomPath=/var/lib/forgejo/custom. Custom templates go to /var/lib/forgejo/custom/templates/custom/ (e.g. footer.tmpl → /var/lib/forgejo/custom/templates/custom/footer.tmpl). Custom static files go to /var/lib/forgejo/custom/public/assets/ (NOT /etc/forgejo/public/assets/) and are served at /assets/*."} +{"_type":"memory","key":"ifcurl-service-names-are-ifcurl-api-service-and","value":"ifcurl service names are ifcurl-api.service and ifcurl-render.service (not ifcurl.service). Install path for Python package: /opt/ifcurl/lib/python3.14/site-packages/ifcurl/. Python binary: /opt/ifcurl/bin/python3."} {"_type":"memory","key":"torawurl-in-viewer-url-js-must-support-github","value":"toRawUrl in viewer-url.js must support GitHub, GitLab, Forgejo/Gitea (codeberg.org, self-hosted), and localhost. Tests in forgejo/tests/viewer-url.test.js cover all four. The localhost check (http vs https) is based on host.startsWith('localhost'), so subdomain.localhost gets https."} diff --git a/forgejo/custom/public/assets/ifcurl.js b/forgejo/custom/public/assets/ifcurl.js index 4385600..6383721 100644 --- a/forgejo/custom/public/assets/ifcurl.js +++ b/forgejo/custom/public/assets/ifcurl.js @@ -29,14 +29,16 @@ function makeViewerLink(info, label, cls) { function linkifyBareIfcUrls() { const IFC_URL = /ifc:\/\/[^\s<>"']+/g; const TRAILING = /[.,;:!?)]+$/; - const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT); const nodes = []; - let n; - while ((n = walker.nextNode())) { - if (n.parentElement.closest('a, code, pre, .ifcurl-preview, [contenteditable]')) continue; - if (IFC_URL.test(n.textContent)) nodes.push(n); - IFC_URL.lastIndex = 0; - } + document.querySelectorAll('.markup').forEach(function(root) { + const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT); + let n; + while ((n = walker.nextNode())) { + if (n.parentElement.closest('a, code, pre, .ifcurl-preview')) continue; + if (IFC_URL.test(n.textContent)) nodes.push(n); + IFC_URL.lastIndex = 0; + } + }); nodes.forEach(function(textNode) { const text = textNode.textContent; const parts = text.split(IFC_URL); @@ -65,8 +67,8 @@ function linkifyBareIfcUrls() { // and bare ifc:// URLs promoted by linkifyBareIfcUrls(). function replaceIfcAnchors() { const origin = window.location.origin; - document.querySelectorAll('a[href^="ifc://"]').forEach(function(a) { - if (a.closest(".ifcurl-preview, [contenteditable]")) return; + document.querySelectorAll('.markup a[href^="ifc://"]').forEach(function(a) { + if (a.closest(".ifcurl-preview")) return; const ifcUrl = a.getAttribute("href"); const img = document.createElement("img"); img.src = origin + "/preview?url=" + encodeURIComponent(ifcUrl);