Test#2
Open
Hackin7 wants to merge 182 commits into
Open
Conversation
This commit also replaces OWL Carousel with GliderJS.
All templates other than index.hbs will continue to use meta_title as the title, while index.hbs will use "Stories".
* Quotes slider with bullets
Bumps [autoprefixer](https://github.com/postcss/autoprefixer) from 10.4.4 to 10.4.7. - [Release notes](https://github.com/postcss/autoprefixer/releases) - [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md) - [Commits](postcss/autoprefixer@10.4.4...10.4.7) --- updated-dependencies: - dependency-name: autoprefixer dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.12 to 8.4.14. - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](postcss/postcss@8.4.12...8.4.14) --- updated-dependencies: - dependency-name: postcss dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [gscan](https://github.com/TryGhost/gscan) from 4.26.1 to 4.31.0. - [Release notes](https://github.com/TryGhost/gscan/releases) - [Commits](TryGhost/gscan@v4.26.1...v4.31.0) --- updated-dependencies: - dependency-name: gscan dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [gscan](https://github.com/TryGhost/gscan) from 4.26.1 to 4.31.2. - [Release notes](https://github.com/TryGhost/gscan/releases) - [Commits](TryGhost/gscan@v4.26.1...v4.31.2) --- updated-dependencies: - dependency-name: gscan dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [@tailwindcss/line-clamp](https://github.com/tailwindlabs/tailwindcss-line-clamp) from 0.3.1 to 0.4.0. - [Release notes](https://github.com/tailwindlabs/tailwindcss-line-clamp/releases) - [Changelog](https://github.com/tailwindlabs/tailwindcss-line-clamp/blob/master/CHANGELOG.md) - [Commits](tailwindlabs/tailwindcss-line-clamp@v0.3.1...v0.4.0) --- updated-dependencies: - dependency-name: "@tailwindcss/line-clamp" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [cssnano](https://github.com/cssnano/cssnano) from 5.1.7 to 5.1.12. - [Release notes](https://github.com/cssnano/cssnano/releases) - [Commits](https://github.com/cssnano/cssnano/compare/cssnano@5.1.7...cssnano@5.1.12) --- updated-dependencies: - dependency-name: cssnano dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
* fix inconsistent fonts and spacing for tagless post * Update post-card.hbs Co-authored-by: Terence Chan Zun Mun <zunmun@gmail.com>
Bumps [gscan](https://github.com/TryGhost/gscan) from 4.31.2 to 4.32.0. - [Release notes](https://github.com/TryGhost/gscan/releases) - [Commits](TryGhost/gscan@v4.31.2...v4.32.0) --- updated-dependencies: - dependency-name: gscan dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [husky](https://github.com/typicode/husky) from 7.0.4 to 8.0.1. - [Release notes](https://github.com/typicode/husky/releases) - [Commits](typicode/husky@v7.0.4...v8.0.1) --- updated-dependencies: - dependency-name: husky dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [gscan](https://github.com/TryGhost/gscan) from 4.32.0 to 4.33.0. - [Release notes](https://github.com/TryGhost/gscan/releases) - [Commits](TryGhost/gscan@v4.32.0...v4.33.0) --- updated-dependencies: - dependency-name: gscan dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
* feat: warning for errors in posts * feat: warning for errors in posts + naming mistake * feat: update post disclaimer
* Update post.hbs Changes the word errors to error * Update post.hbs Changed the word error to errors * Padding has been increased
* Update footer.hbs * Update page-team.hbs * fix: team page height entry fix --------- Co-authored-by: Terence Chan Zun Mun <zunmun@gmail.com>
Ubuntu version is fixed to LTS 24.04, consistent with production.
…ws (#483) * docs(specs): add sort/filter design for events and interviews Captures the brainstorming output for two features (overview index) and the full design spec for Feature 1 — multi-tag client-side filtering on the /events/ and /interviews/ collections, with URL sync and load-more pagination. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(plans): add implementation plan for events/interviews sort+filter Twelve-task TDD-light plan derived from 2026-05-06-sort-filter-design.md, covering Alpine component, partial, template wiring, routes update, accessibility, SEO canonical, graceful-degradation and final scenario sweep. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(post-card): expose public tags via data attributes * fix(post-card): pipe-separate tag names, single-quote visibility arg * feat(js): add postFilterList Alpine component Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(filter): single DOM walk and document component contracts * feat(events): add multi-tag filter and load-more * fix(filter): hoist x-cloak to utils, doc isVisible contract, limit=all * feat(interviews): add filter using shared partial * fix(filter): align template filter strings with routes.yaml tag variants Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(templates): doc filter sync with routes; degenericise index.hbs * fix(filter): a11y checkmark, scoped tabindex, empty-state clear button * docs(specs): add search/sort/full-load design for events and interviews Extends the prior tag-filter feature with: Typesense-backed search, 4-option sort dropdown, and approach-A template pagination (20 blocks, 2000 ceiling) to fix the limit='all' cap at 100 posts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(plans): add implementation plan for search/sort/full-load 9 tasks ordered: full-corpus load (1) → sort (2-4) → search (5-8) → end-to-end verification (9). Each implementation task ends with build, gscan lint, manual browser check, and commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(filter): full-corpus load via 20 stacked {{#get}} page blocks * docs(filter): preserve focus rationale + clarify Ghost's 100/page max Re-add the comment explaining tabindex="-1" enables loadMore() focus (lost during the sub-partial extraction) and document that limit=100 is Ghost's per-page cap, not an arbitrary choice. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(post-card): expose slug, title, published-at as data attributes * feat(filter): add client-side sort with URL sync * refactor(filter): hoist VALID_SORTS, document _reorderDom parent assumption Hoist the four-mode allowlist to a module constant so the URL parser, the dropdown UI (Task 4), and the sort comparator share one source of truth. Document the implicit single-parent assumption in _reorderDom so a future partial split won't silently re-parent cards. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(filter): add sort dropdown to toolbar * style(filter): align toolbar bottom-margin with chip row (mb-4 -> mb-6) Match the established mb-6 cadence used by the chip row directly below. Keeps vertical rhythm consistent now that toolbar precedes chips. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(search): add Typesense search wrapper * feat(filter): thread page tagSlugs into Alpine component for search scoping * docs(filter): document tagSlugs/filter mirror requirement The slug list now appears in two formats per page (Ghost filter syntax + plain comma-separated). Comment explains the constraint so future edits don't drift one without the other. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(search): integrate Typesense search into filter pipeline * fix(search): prevent isSearching flicker, abort on clearFilters Two correctness fixes surfaced in code review before Task 8 wires the UI: 1. _runSearch now captures the AbortController locally so finally{} only clears isSearching when THIS call is still the latest. Otherwise rapid typing makes the spinner flicker off when the aborted call's finally fires while the superseding call is still in flight. 2. clearFilters now aborts any in-flight search, clears the debounce timer, and forces a URL write. Without this, a stale Typesense response could land after the clear and re-populate searchSlugs, and ?sort= or ?q= could linger in the URL when their watchers weren't dirty. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(search): add search input, indicator, banner, and empty-state adaptation * fix(search): inline min-width, drop redundant Esc refocus, unify ellipsis Tailwind 3.0 JIT in this project doesn't reliably emit arbitrary values like min-w-[200px], so the toolbar would have collapsed below the intended threshold on narrow viewports. Inline style guarantees the constraint regardless of the JIT scan. Also: $event.target.focus() in the Esc handler is a no-op (the input already has focus when Esc fires) — drop. And use the U+2026 ellipsis in the placeholder to match the Searching… indicator. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(filter): close UX gaps from final review (Esc lag, stale URL, DRY) Four cleanups from the whole-branch review: 1. setSearchQuery short-circuits to immediate _runSearch when input is empty/sub-threshold. Previously Esc-to-clear left the URL ?q= and result count stale for the full 250ms debounce window. 2. init() normalizes sub-threshold ?q= values to '' so a hand-crafted /events/?q=x doesn't sit in the input with no active search behind it. 3. New hasActiveFilters() getter consolidates the "tags || search || sort != newest" expression that had been duplicated in three x-show bindings. 4. Refresh stale "Not consumed in Task 3" comment on the tagSlugs constructor parameter — now describes its actual role (Typesense filter_by scoping). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(search): move Typesense config to package.json config.custom Three Typesense settings (host, api_key, collection) move from JS-file constants to package.json config.custom defaults, admin-overridable in Ghost → Design → Customize. default.hbs injects the resolved values into window.__TYPESENSE_CONFIG__ before the bundle loads, and the wrapper reads from there at search time (with the same defaults as fallback for partial-page-render contexts). Operationally: deploying to a different Ghost instance no longer requires editing the theme — admins point the search at their own Typesense backend via the Customize panel. The API key remains search-only by design (read-only, public-scoped). Adds a "Typesense Search" section to README documenting the three settings and the security model of the embedded key. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: base dropdown * feat: make it look nicer --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(specs): add targeted related-posts design
Replaces the bottom-of-article widget's "any shared tag" matching
with Typesense semantic ranking on title+excerpt, with the existing
tag-matched SSR rendering serving as both the no-JS fallback AND the
topup pool when Typesense returns < 3 hits. Cross-collection scope.
3-card layout preserved.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(plans): add implementation plan for targeted related-posts
8 tasks: Typesense plumbing (config + wrapper), post-card data-slug,
Alpine component with card builder, partial wrapper changes, main.js
registration, README, end-to-end manual verification.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(config): add Typesense config to package.json + default.hbs
* feat(search): add Typesense searchSimilar wrapper
* feat(post-card): expose slug as data attribute for related-posts JS
* feat(related): add Alpine component with Typesense fetch + card builder
* fix(related): self-exclusion uses id, document post-card divergences
Three cleanups from code review of Task 4:
1. The defensive filter dropping the source post compared h.slug to
source.id — different value spaces (slug vs ObjectId hex), so the
guard was dead code. Add 'id' to Typesense include_fields and
compare on h.id, restoring the safety net the comment claimed.
2. Document the two intentional divergences from post-card.hbs in the
buildCardElement comment block: hardcoded "feed-card post" instead
of {{post_class}} (verified safe — no CSS targets per-post tag-{slug}
classes), and omitted <img> when feature_image is empty (post-card
uses a hidden placeholder; both are display:none).
3. pickPrimaryTag drops the type-confusing "|| hit.tags" fallback —
tags.name is always requested in include_fields so the fallback
couldn't help, and hit.tags has a different shape that would make
names[i] return an object instead of a string.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(related): wrap with Alpine component, source data on data-attrs
* feat(related): register relatedPosts Alpine component
* docs(readme): document Typesense search configuration
Adds a new section explaining the three custom-config fields, the
search-only key security model, and where to override per-install.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(post-card): cross-reference the JS card builder mirror
Final-review item: makes the JS↔HBS mirror contract discoverable from
the HBS side. A future contributor changing post-card.hbs now has a
breadcrumb to assets/js/related-posts.js → buildCardElement().
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(related): exclude self by id AND slug, in case one identifier is empty
User reported the recommended-articles widget was including the article
itself. Live verification of Typesense's filter_by=id:!=X showed it
works correctly, so the bug must be on our side: source.id from
data-post-id="{{post.id}}" was likely empty for some reason, making
the wrapper's `if (excludeId)` gate skip the filter, AND making the
JS defensive filter useless (h.id !== '' is always true).
Three layers of defense added:
1. Partial now exposes data-post-slug="{{post.slug}}" alongside
data-post-id. Slug is the most reliable identifier (also in the
page URL and on every post-card).
2. typesense-search.js gains an excludeSlug option. When both are
passed, filter_by combines them with && so a doc matching either
identifier is excluded server-side.
3. JS defensive filter now checks id, slug, AND url — any one match
triggers exclusion. Empty source identifiers are skipped (no false
positives where empty string matches empty field).
Verified live: filter_by=slug:!=X excludes the named post correctly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(related): rewrite Typesense URLs to current origin (no more cross-site jumps)
Typesense indexes posts with production-absolute URLs
(https://advisory.sg/...). The JS card builder consumed hit.url verbatim
for both the inner div onclick and the stretch-link href, so clicking a
related card on localhost:2368 navigated the user OFF-SITE to the prod
domain. SSR cards were already correct because Ghost's {{url}} helper
resolves against @site.url.
Add a toLocalPath() helper that returns just pathname+search+hash from
any URL (absolute, relative, or malformed). The browser then resolves
the result against the current page's origin: localhost stays on
localhost, prod stays on prod, no environment-specific config.
Apply at three sites: the onclick interpolation, the stretch-link href,
and the defensive self-exclusion URL check (which previously compared
full URLs and never matched on localhost — now compares paths).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.