Frontmatter
| id | 12208 |
| title | Extract the shared timeline contract into Neo.app.content.Component |
| state | Closed |
| labels | enhancementairefactoring |
| assignees | neo-opus-ada |
| createdAt | May 30, 2026, 7:25 PM |
| updatedAt | May 31, 2026, 12:29 AM |
| githubUrl | https://github.com/neomjs/neo/issues/12208 |
| author | neo-opus-ada |
| commentsCount | 0 |
| parentIssue | 12204 |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [x] 12207 Rename timeline-node model/store TicketTimelineSection(s) → TimelineSection(s), [x] 12206 Promote portal canvas view-glue (bridge + CanvasWrapper) to shared |
| blocking | [x] 12209 Make portal content cross-link URLs per-content-type config |
| closedAt | May 31, 2026, 12:29 AM |
Context
Part of epic #12207 (foundation step 4). The per-type parsers (issue/PR/discussion) share scaffolding that belongs in the framework Component so each type only supplies its parser.
The Fix
Lift the SHARED scaffolding up into
Neo.app.content.Component(or aTimelineContentbase/mixin): the timeline-item / comment-item / body-item HTML templates,formatTimestamp, thesections-store push, and the IntersectionObserver wiring (it targets.neo-timeline-item[data-record-id]generically). Keep the issue-specificrenderTimelineline-walker + the event-type/label/commit machinery inapps/portal/view/news/tickets/Component.mjsas the Issue specialization.Architectural Reality
tickets/Component.mjs:271-402(modifyMarkdown pipeline),:425-584(renderTimeline),:479-489(issue event-type table). The shared seam is the OUTPUT contract — all parsers emit the same{id, image|color, icon, name, tag}nodes +.neo-timeline-itemHTML; the canvas never parses markdown.Acceptance Criteria
modifyMarkdown/renderTimelineparser.Related
Epic #12207. Depends on foundation steps 2 + 3; unblocks the per-type views (7, 8) and step 5.