From a7a948885ddedc1c1f4dab1d9c5aa24935d5ece2 Mon Sep 17 00:00:00 2001 From: herr kaste Date: Tue, 21 Jul 2026 14:31:31 +0200 Subject: [PATCH 1/2] Fix tombstones always being marked as ST2 Infer Sublime Text compatibility once and derive the ST2/ST3 labels, outdated flag, and st3_only flag from that value. Let empty release lists produce unknown compatibility, which avoids inferring ST labels for skeleton tombstones. --- eleventy.config.mjs | 18 +++++------- eleventy.config.test.mjs | 46 ++++++++++++++++++++++++++++++ eleventy.util.mjs | 61 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 eleventy.config.test.mjs diff --git a/eleventy.config.mjs b/eleventy.config.mjs index 1b618d829..ebb50e24e 100644 --- a/eleventy.config.mjs +++ b/eleventy.config.mjs @@ -216,7 +216,7 @@ function computeMagicMetadata(packages) { }) } -function basePackage(pkg) { +export function basePackage(pkg) { // Create a new array of releases with cleaned platforms const rawReleases = pkg.releases || [] const releases = rawReleases.map(release => ({ @@ -225,12 +225,7 @@ function basePackage(pkg) { platforms: util.prettifyPlatformLabels(release.platforms), })) - const supportsModernSublime = releases.some((release) => { - return util.parseSublimeTextMin(release.sublime_text) >= 3000 - }) - const doesNotSupportNewestSublime = releases.every((release) => { - return util.parseSublimeTextMax(release.sublime_text) < 4000 - }) + const compatibility = util.computeSublimeCompatibility(releases) // For each release, infer a human web URL under key "web" // Rules: @@ -281,9 +276,9 @@ function basePackage(pkg) { if (pkg.failing_since || pkg.fail_reason) { labels.unshift('FAILING') } - if (!supportsModernSublime) { + if (compatibility === 'st2') { labels.unshift('ST2') - } else if (doesNotSupportNewestSublime) { + } else if (compatibility === 'st3') { labels.unshift('ST3') } if (pkg.removed) { @@ -307,8 +302,9 @@ function basePackage(pkg) { platforms: platforms, // Human-readable label shown on cards and package stats/labels. platform_statement: util.computePlatformStatement(platforms), - outdated: !supportsModernSublime, - st3_only: supportsModernSublime && doesNotSupportNewestSublime, + compatibility, + outdated: compatibility === 'st2', + st3_only: compatibility === 'st3', } } diff --git a/eleventy.config.test.mjs b/eleventy.config.test.mjs new file mode 100644 index 000000000..00c5ccd98 --- /dev/null +++ b/eleventy.config.test.mjs @@ -0,0 +1,46 @@ +import { describe, expect, it } from 'vitest' +import { basePackage } from './eleventy.config.mjs' + +describe('basePackage compatibility labels', () => { + it('does not infer ST labels for skeleton tombstones', () => { + const pkg = basePackage({ + name: 'Yollama', + labels: ['auto-complete', 'ai', 'assistant'], + first_seen: '2024-02-19T21:02:58Z', + removed: '2025-11-16T12:38:48Z', + }) + + expect(pkg.labels).toEqual(['RIP', 'auto-complete', 'ai', 'assistant']) + expect(pkg.compatibility).toBeNull() + expect(pkg.outdated).toBe(false) + expect(pkg.st3_only).toBe(false) + }) + + it('derives ST2 labels and flags from compatibility', () => { + const pkg = basePackage({ + name: 'Old Package', + releases: [ + { version: '1.0.0', sublime_text: '<3000', platforms: ['*'] }, + ], + }) + + expect(pkg.labels).toEqual(['ST2']) + expect(pkg.compatibility).toBe('st2') + expect(pkg.outdated).toBe(true) + expect(pkg.st3_only).toBe(false) + }) + + it('derives ST3 labels and flags from compatibility', () => { + const pkg = basePackage({ + name: 'ST3 Package', + releases: [ + { version: '1.0.0', sublime_text: '3000-3999', platforms: ['*'] }, + ], + }) + + expect(pkg.labels).toEqual(['ST3']) + expect(pkg.compatibility).toBe('st3') + expect(pkg.outdated).toBe(false) + expect(pkg.st3_only).toBe(true) + }) +}) diff --git a/eleventy.util.mjs b/eleventy.util.mjs index 205d5f984..0f05da2a0 100644 --- a/eleventy.util.mjs +++ b/eleventy.util.mjs @@ -619,6 +619,41 @@ function toLiveFileUrl(url) { ) } +/** + * @typedef {'st2' | 'st3' | 'current'} SublimeCompatibility + */ + +/** + * Infer Sublime Text compatibility from release selectors. + * + * Returns null when release data is unavailable, such as for skeleton + * tombstones. + * + * @param {Array<{sublime_text?: string}>} releases + * @returns {SublimeCompatibility | null} + */ +export function computeSublimeCompatibility(releases) { + if (releases.length === 0) { + return null + } + + const supportsModernSublime = releases.some((release) => { + return parseSublimeTextMin(release.sublime_text) >= 3000 + }) + if (!supportsModernSublime) { + return 'st2' + } + + const doesNotSupportNewestSublime = releases.every((release) => { + return parseSublimeTextMax(release.sublime_text) < 4000 + }) + if (doesNotSupportNewestSublime) { + return 'st3' + } + + return 'current' +} + /** * Convert a Sublime Text build selector into its starting build number. * Rules: @@ -862,6 +897,32 @@ if (import.meta.vitest) { }) }) + describe('computeSublimeCompatibility', () => { + it('returns null when release data is unavailable', () => { + expect(computeSublimeCompatibility([])).toBeNull() + }) + + it('detects ST2-only packages', () => { + expect(computeSublimeCompatibility([ + { sublime_text: '<3000' }, + { sublime_text: '2000' }, + ])).toBe('st2') + }) + + it('detects ST3-only packages', () => { + expect(computeSublimeCompatibility([ + { sublime_text: '3000-3999' }, + { sublime_text: '3000' }, + ])).toBe('st3') + }) + + it('detects packages compatible with current Sublime Text', () => { + expect(computeSublimeCompatibility([ + { sublime_text: '*' }, + ])).toBe('current') + }) + }) + describe('parseSublimeTextMin', () => { it.each([ [null, 0], From 348216bd6b69b42515102dbfdb8748d2eb95cd24 Mon Sep 17 00:00:00 2001 From: herr kaste Date: Tue, 21 Jul 2026 14:32:50 +0200 Subject: [PATCH 2/2] Drop unused st3_only field Remove the st3_only boolean from package metadata, the compact search index, MiniSearch stored fields, and compatibility tests. The ST3 synthetic label remains the user-visible state. --- eleventy.config.mjs | 1 - eleventy.config.test.mjs | 3 --- eleventy.filters.mjs | 3 +-- static/module/minisearch.js | 1 - static/package-search.js | 2 -- 5 files changed, 1 insertion(+), 9 deletions(-) diff --git a/eleventy.config.mjs b/eleventy.config.mjs index ebb50e24e..611a9e5c9 100644 --- a/eleventy.config.mjs +++ b/eleventy.config.mjs @@ -304,7 +304,6 @@ export function basePackage(pkg) { platform_statement: util.computePlatformStatement(platforms), compatibility, outdated: compatibility === 'st2', - st3_only: compatibility === 'st3', } } diff --git a/eleventy.config.test.mjs b/eleventy.config.test.mjs index 00c5ccd98..01e7b27db 100644 --- a/eleventy.config.test.mjs +++ b/eleventy.config.test.mjs @@ -13,7 +13,6 @@ describe('basePackage compatibility labels', () => { expect(pkg.labels).toEqual(['RIP', 'auto-complete', 'ai', 'assistant']) expect(pkg.compatibility).toBeNull() expect(pkg.outdated).toBe(false) - expect(pkg.st3_only).toBe(false) }) it('derives ST2 labels and flags from compatibility', () => { @@ -27,7 +26,6 @@ describe('basePackage compatibility labels', () => { expect(pkg.labels).toEqual(['ST2']) expect(pkg.compatibility).toBe('st2') expect(pkg.outdated).toBe(true) - expect(pkg.st3_only).toBe(false) }) it('derives ST3 labels and flags from compatibility', () => { @@ -41,6 +39,5 @@ describe('basePackage compatibility labels', () => { expect(pkg.labels).toEqual(['ST3']) expect(pkg.compatibility).toBe('st3') expect(pkg.outdated).toBe(false) - expect(pkg.st3_only).toBe(true) }) }) diff --git a/eleventy.filters.mjs b/eleventy.filters.mjs index ec8247587..ac04f6547 100644 --- a/eleventy.filters.mjs +++ b/eleventy.filters.mjs @@ -122,10 +122,9 @@ function compactSearchPackage(pkg) { (pkg.labels ?? []).join(','), ] - if (pkg.outdated || pkg.st3_only || pkg.removed || pkg.archived_at) { + if (pkg.outdated || pkg.removed || pkg.archived_at) { row.push( pkg.outdated ? 1 : 0, - pkg.st3_only ? 1 : 0, timestamp(pkg.removed) || 0, timestamp(pkg.archived_at) || 0, ) diff --git a/static/module/minisearch.js b/static/module/minisearch.js index db0c72354..91b0cf953 100644 --- a/static/module/minisearch.js +++ b/static/module/minisearch.js @@ -61,7 +61,6 @@ function createMinisearchInstance(MiniSearch) { 'magic_score', 'magic', 'outdated', - 'st3_only', ], searchOptions: { boost: { author: 2, name: 2 }, diff --git a/static/package-search.js b/static/package-search.js index f5c01a882..f1472efda 100644 --- a/static/package-search.js +++ b/static/package-search.js @@ -68,7 +68,6 @@ function expandSearchPackage(row) { platform_statement, labels, outdated, - st3_only, removed, archived_at, ] = row @@ -87,7 +86,6 @@ function expandSearchPackage(row) { platform_statement, labels, ...(outdated ? { outdated: true } : {}), - ...(st3_only ? { st3_only: true } : {}), ...(removed ? { removed } : {}), ...(archived_at ? { archived_at } : {}), }