From 4057ff23a26aa9ce4cbffb460ce1c61e8dd5e108 Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Fri, 25 Oct 2024 00:03:49 +0200 Subject: [PATCH 01/42] Sketch out `` component --- demo/src/pages/baseline-status.astro | 14 + demo/src/pages/index.astro | 3 + package-lock.json | 12 + .../BaselineIcon.astro | 51 +++ .../BaselineStatus.astro | 318 ++++++++++++++++++ .../BrowserIcon.astro | 16 + .../SupportIcon.astro | 28 ++ packages/astro-embed-baseline-status/index.ts | 1 + .../astro-embed-baseline-status/package.json | 22 ++ packages/astro-embed-baseline-status/types.ts | 14 + 10 files changed, 479 insertions(+) create mode 100644 demo/src/pages/baseline-status.astro create mode 100644 packages/astro-embed-baseline-status/BaselineIcon.astro create mode 100644 packages/astro-embed-baseline-status/BaselineStatus.astro create mode 100644 packages/astro-embed-baseline-status/BrowserIcon.astro create mode 100644 packages/astro-embed-baseline-status/SupportIcon.astro create mode 100644 packages/astro-embed-baseline-status/index.ts create mode 100644 packages/astro-embed-baseline-status/package.json create mode 100644 packages/astro-embed-baseline-status/types.ts diff --git a/demo/src/pages/baseline-status.astro b/demo/src/pages/baseline-status.astro new file mode 100644 index 0000000..c95b5fc --- /dev/null +++ b/demo/src/pages/baseline-status.astro @@ -0,0 +1,14 @@ +--- +import { BaselineStatus } from '@astro-community/astro-embed-baseline-status'; +import Base from '../layouts/Base.astro'; +--- + + +

Default

+

+ <BaselineStatus id="anchor-positioning" /> +

+ + diff --git a/demo/src/pages/index.astro b/demo/src/pages/index.astro index 01d2126..2686bdf 100644 --- a/demo/src/pages/index.astro +++ b/demo/src/pages/index.astro @@ -19,6 +19,9 @@ import Base from '../layouts/Base.astro'; ><LinkPreview/> component examples +
  • + <BaselineStatus/> component examples +
  • Other examples

      diff --git a/package-lock.json b/package-lock.json index 991da47..05a145d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -74,6 +74,10 @@ "node": ">=6.0.0" } }, + "node_modules/@astro-community/astro-embed-baseline-status": { + "resolved": "packages/astro-embed-baseline-status", + "link": true + }, "node_modules/@astro-community/astro-embed-demo": { "resolved": "demo", "link": true @@ -12573,6 +12577,14 @@ "astro": "^2.0.0 || ^3.0.0-beta || ^4.0.0-beta || ^5.0.0-beta" } }, + "packages/astro-embed-baseline-status": { + "name": "@astro-community/astro-embed-baseline-status", + "version": "0.0.1", + "license": "MIT", + "dependencies": { + "@astro-community/astro-embed-utils": "^0.1.0" + } + }, "packages/astro-embed-integration": { "name": "@astro-community/astro-embed-integration", "version": "0.7.2", diff --git a/packages/astro-embed-baseline-status/BaselineIcon.astro b/packages/astro-embed-baseline-status/BaselineIcon.astro new file mode 100644 index 0000000..8e30aed --- /dev/null +++ b/packages/astro-embed-baseline-status/BaselineIcon.astro @@ -0,0 +1,51 @@ +--- +interface Props { + support: 'widely' | 'newly' | 'limited' | 'no_data'; +} +--- + + + + diff --git a/packages/astro-embed-baseline-status/BaselineStatus.astro b/packages/astro-embed-baseline-status/BaselineStatus.astro new file mode 100644 index 0000000..93d0980 --- /dev/null +++ b/packages/astro-embed-baseline-status/BaselineStatus.astro @@ -0,0 +1,318 @@ +--- +import { safeGet } from '@astro-community/astro-embed-utils'; +import BaselineIcon from './BaselineIcon.astro'; +import BrowserIcon from './BrowserIcon.astro'; +import SupportIcon from './SupportIcon.astro'; +import type { Feature } from './types'; + +interface Props { + /** + * ID of the feature from https://github.com/web-platform-dx/web-features/ + * e.g. `"anchor-positioning"` + */ + id: string; +} + +type StatusLevel = 'widely' | 'newly' | 'limited' | 'no_data'; + +const API_ENDPOINT = 'https://api.webstatus.dev/v1/features/'; + +const BASELINE_DEFS = { + limited: { + title: 'Limited availability', + defaultDescription: + 'This feature is not Baseline because it does not work in some of the most widely-used browsers.', + }, + newly: { + title: '', + defaultDescription: + 'This feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.', + }, + widely: { + title: 'Widely available', + defaultDescription: + 'This feature is well established and works across many devices and browser versions.', + }, + loading: { + title: 'Loading', + defaultDescription: '', + }, + no_data: { + title: 'Unknown availability', + defaultDescription: + 'We currently don’t have browser support information about this feature.', + }, +}; + +/** + * Returns feature's `low_date` as mm-yyyy string or empty string if `low_date` is not present. + */ +function getBaselineDate(feature: { baseline: { low_date?: string } }): string { + return feature.baseline.low_date + ? new Intl.DateTimeFormat('en-US', { + year: 'numeric', + month: 'long', + }).format(new Date(feature.baseline.low_date)) + : ''; +} + +/** + * Returns Baseline's description. + */ +function getDescriptionDate(baseline: StatusLevel, date: string): string { + if (baseline === 'newly' && date) { + return `Since ${date} this feature works across the latest + devices and browser versions. This feature might not work in older + devices or browsers.`; + } else if (baseline === 'widely' && date) { + return `This feature is well established and works across many + devices and browser versions. It’s been available across browsers + since ${date}`; + } + return BASELINE_DEFS[baseline].defaultDescription; +} + +const featureData = await safeGet(API_ENDPOINT + Astro.props.id); +const feature: Feature = featureData?.baseline + ? (featureData as Feature) + : { + baseline: { + status: 'no_data', + }, + name: Astro.props.id || 'Unknown feature', + }; + +const baseline = feature.baseline.status || 'no_data'; + +const preTitle = + baseline === 'limited' || baseline === 'no_data' + ? '' + : `Baseline `; +const title = BASELINE_DEFS[baseline].title; +const badge = + baseline === 'newly' + ? `newly available` + : ''; +const baselineDate = getBaselineDate(feature); +const description = getDescriptionDate(baseline, baselineDate); +const year = + baseline === 'newly' && baselineDate ? baselineDate.split(' ')[1]! : ''; + +const { chrome, edge, firefox, safari } = feature.browser_implementations || {}; + +const getAriaLabel = ( + title: string, + year: string, + badge: string, + chrome = 'no', + edge = 'no', + firefox = 'no', + safari = 'no' +) => { + if (title === 'Unknown availability') { + chrome = edge = firefox = safari = 'unknown'; + } + return `Baseline: ${title}${year ? ` ${year}` : ''}${ + badge ? ` (newly available)` : '' + }. Supported in Chrome: ${ + chrome === 'available' ? 'yes' : chrome + }. Supported in Edge: ${ + edge === 'available' ? 'yes' : edge + }. Supported in Firefox: ${ + firefox === 'available' ? 'yes' : firefox + }. Supported in Safari: ${safari === 'available' ? 'yes' : safari}.`; +}; +--- + + +

      {feature.name}

      +
      + + + + + +

      +

      Learn more`} + /> +

      +
      + + diff --git a/packages/astro-embed-baseline-status/BrowserIcon.astro b/packages/astro-embed-baseline-status/BrowserIcon.astro new file mode 100644 index 0000000..2eb8f5f --- /dev/null +++ b/packages/astro-embed-baseline-status/BrowserIcon.astro @@ -0,0 +1,16 @@ +--- +import type { Browser } from './types'; + +interface Props { + browser: Browser; +} + +const ICONS = { + chrome: ``, + edge: ``, + firefox: ``, + safari: ``, +}; +--- + + diff --git a/packages/astro-embed-baseline-status/SupportIcon.astro b/packages/astro-embed-baseline-status/SupportIcon.astro new file mode 100644 index 0000000..2e7c450 --- /dev/null +++ b/packages/astro-embed-baseline-status/SupportIcon.astro @@ -0,0 +1,28 @@ +--- +import type { BrowserImplementation, StatusLevel } from './types'; + +interface Props { + baseline: StatusLevel; + browserImplementation?: BrowserImplementation | undefined; +} + +const { baseline, browserImplementation } = Astro.props; + +const SUPPORT_ICONS = { + available: ``, + unavailable: ``, + no_data: ``, +}; + +const support = + baseline === 'limited' + ? browserImplementation?.status || 'unavailable' + : baseline; +const icon = + support === 'newly' || support === 'widely' ? 'available' : support; +--- + + diff --git a/packages/astro-embed-baseline-status/index.ts b/packages/astro-embed-baseline-status/index.ts new file mode 100644 index 0000000..5e7dde9 --- /dev/null +++ b/packages/astro-embed-baseline-status/index.ts @@ -0,0 +1 @@ +export { default as BaselineStatus } from './BaselineStatus.astro'; diff --git a/packages/astro-embed-baseline-status/package.json b/packages/astro-embed-baseline-status/package.json new file mode 100644 index 0000000..ba3b2a8 --- /dev/null +++ b/packages/astro-embed-baseline-status/package.json @@ -0,0 +1,22 @@ +{ + "name": "@astro-community/astro-embed-baseline-status", + "version": "0.0.1", + "description": "Component to easily embed the Baseline status of a web feature on your Astro site", + "type": "module", + "exports": { + ".": "./index.ts", + "./matcher": "./matcher.ts" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/delucis/astro-embed.git" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/delucis/astro-embed/issues" + }, + "homepage": "https://github.com/delucis/astro-embed/tree/main/packages/astro-embed-baseline-status#readme", + "dependencies": { + "@astro-community/astro-embed-utils": "^0.1.0" + } +} diff --git a/packages/astro-embed-baseline-status/types.ts b/packages/astro-embed-baseline-status/types.ts new file mode 100644 index 0000000..d5bdc3b --- /dev/null +++ b/packages/astro-embed-baseline-status/types.ts @@ -0,0 +1,14 @@ +export type StatusLevel = 'widely' | 'newly' | 'limited' | 'no_data'; +export type SupportLevel = 'available' | 'unavailable' | 'no_data'; +export type Browser = 'chrome' | 'edge' | 'firefox' | 'safari'; + +export interface BrowserImplementation { + status: SupportLevel; +} + +export interface Feature { + name: string; + feature_id?: string; + browser_implementations?: Record; + baseline: { status?: StatusLevel; low_date?: string }; +} From ce197957d657ba534d42606c42a7f409c08f143a Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Fri, 25 Oct 2024 00:32:40 +0200 Subject: [PATCH 02/42] Fix duplicated types --- packages/astro-embed-baseline-status/BaselineIcon.astro | 4 +++- packages/astro-embed-baseline-status/BaselineStatus.astro | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/astro-embed-baseline-status/BaselineIcon.astro b/packages/astro-embed-baseline-status/BaselineIcon.astro index 8e30aed..ba45ce9 100644 --- a/packages/astro-embed-baseline-status/BaselineIcon.astro +++ b/packages/astro-embed-baseline-status/BaselineIcon.astro @@ -1,6 +1,8 @@ --- +import type { StatusLevel } from './types'; + interface Props { - support: 'widely' | 'newly' | 'limited' | 'no_data'; + support: StatusLevel; } --- diff --git a/packages/astro-embed-baseline-status/BaselineStatus.astro b/packages/astro-embed-baseline-status/BaselineStatus.astro index 93d0980..04290ed 100644 --- a/packages/astro-embed-baseline-status/BaselineStatus.astro +++ b/packages/astro-embed-baseline-status/BaselineStatus.astro @@ -3,7 +3,7 @@ import { safeGet } from '@astro-community/astro-embed-utils'; import BaselineIcon from './BaselineIcon.astro'; import BrowserIcon from './BrowserIcon.astro'; import SupportIcon from './SupportIcon.astro'; -import type { Feature } from './types'; +import type { Feature, StatusLevel } from './types'; interface Props { /** @@ -13,8 +13,6 @@ interface Props { id: string; } -type StatusLevel = 'widely' | 'newly' | 'limited' | 'no_data'; - const API_ENDPOINT = 'https://api.webstatus.dev/v1/features/'; const BASELINE_DEFS = { From e0453152b14af9bd328aea9ab8b865b8a503351b Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Fri, 25 Oct 2024 00:46:10 +0200 Subject: [PATCH 03/42] Clean up some templating issues --- .../BaselineStatus.astro | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/packages/astro-embed-baseline-status/BaselineStatus.astro b/packages/astro-embed-baseline-status/BaselineStatus.astro index 04290ed..f88d2ee 100644 --- a/packages/astro-embed-baseline-status/BaselineStatus.astro +++ b/packages/astro-embed-baseline-status/BaselineStatus.astro @@ -31,10 +31,6 @@ const BASELINE_DEFS = { defaultDescription: 'This feature is well established and works across many devices and browser versions.', }, - loading: { - title: 'Loading', - defaultDescription: '', - }, no_data: { title: 'Unknown availability', defaultDescription: @@ -82,36 +78,27 @@ const feature: Feature = featureData?.baseline const baseline = feature.baseline.status || 'no_data'; -const preTitle = - baseline === 'limited' || baseline === 'no_data' - ? '' - : `Baseline `; const title = BASELINE_DEFS[baseline].title; -const badge = - baseline === 'newly' - ? `newly available` - : ''; const baselineDate = getBaselineDate(feature); const description = getDescriptionDate(baseline, baselineDate); const year = baseline === 'newly' && baselineDate ? baselineDate.split(' ')[1]! : ''; - const { chrome, edge, firefox, safari } = feature.browser_implementations || {}; -const getAriaLabel = ( +function getAriaLabel( title: string, year: string, - badge: string, + newlyAvailable: boolean, chrome = 'no', edge = 'no', firefox = 'no', safari = 'no' -) => { +) { if (title === 'Unknown availability') { chrome = edge = firefox = safari = 'unknown'; } return `Baseline: ${title}${year ? ` ${year}` : ''}${ - badge ? ` (newly available)` : '' + newlyAvailable ? ` (newly available)` : '' }. Supported in Chrome: ${ chrome === 'available' ? 'yes' : chrome }. Supported in Edge: ${ @@ -119,7 +106,7 @@ const getAriaLabel = ( }. Supported in Firefox: ${ firefox === 'available' ? 'yes' : firefox }. Supported in Safari: ${safari === 'available' ? 'yes' : safari}.`; -}; +} --- @@ -129,7 +116,7 @@ const getAriaLabel = ( aria-label={getAriaLabel( title, year, - badge, + baseline === 'newly', chrome?.status, edge?.status, firefox?.status, @@ -138,24 +125,37 @@ const getAriaLabel = ( >