Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/stamped-versions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@nasa-hds/core': patch
---

Stamp the HDS and USWDS versions into the compiled CSS

Every bundle now opens with a banner naming its version and the USWDS version it was built against, and `hds.min.css` exposes `--hds-version` and `--hds-uswds-version` for runtime reads. These are diagnostics for copied-`dist/` deployments that keep no other record of what is installed; both values belong in any bug report. See [Installation](?path=/docs/overview-installation--docs) for how to read them.
66 changes: 66 additions & 0 deletions .config/postcss-hds-stamp.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* HDS Version Stamp — PostCSS plugin
*
* Stamps the HDS + USWDS versions into every compiled bundle: a `/*!` banner
* on all bundles, plus --hds-version / --hds-uswds-version on :root in
* hds.min.css only (a stale copy of an optional bundle must not win the
* cascade and misreport the version).
*
* Runs last in the postcss chain so the banner survives comment-discarding
* and minification. Versions are read at build time, so the stamp tracks the
* changesets bump with nothing to regenerate.
*/

import fs from 'node:fs';

const read = (path) => JSON.parse(fs.readFileSync(path, 'utf8'));

const HDS_VERSION = read('./package.json').version;
const USWDS_VERSION = read('./node_modules/@uswds/uswds/package.json').version;

/** Bundles that carry the custom properties, keyed by output filename. */
const STAMPS_PROPERTIES = new Set(['hds.min.css', 'hds.css']);

export default function hdsStamp() {
return {
postcssPlugin: 'postcss-hds-stamp',

OnceExit(root, { result, Comment, Rule, Declaration, AtRule }) {
const file = result.opts.to ? result.opts.to.split(/[\\/]/).pop() : '';

// We compile USWDS from source, so its banner ships the literal
// `uswds @version` placeholder that USWDS substitutes in its own build.
root.walkComments((comment) => {
if (comment.text.includes('uswds @version')) {
comment.text = comment.text.replace('uswds @version', `uswds v${USWDS_VERSION}`);
}
});

if (STAMPS_PROPERTIES.has(file)) {
const rule = new Rule({ selector: ':root' });
// Unquoted: `getPropertyValue('--hds-version')` then reads back as
// `0.9.0` rather than `'0.9.0'`, which is what a support request or a
// console one-liner actually wants.
rule.append(new Declaration({ prop: '--hds-version', value: HDS_VERSION }));
rule.append(new Declaration({ prop: '--hds-uswds-version', value: USWDS_VERSION }));

// hds-base is already declared in every bundle's layer order;
// layers merge, so appending here needs no other coordination.
const layer = new AtRule({ name: 'layer', params: 'hds-base' });
layer.append(rule);
root.append(layer);
}

const banner = new Comment({
text: `! @nasa-hds/core v${HDS_VERSION}${file ? ` — ${file}` : ''} | uswds v${USWDS_VERSION} | CC0 1.0 | https://github.com/nasa/hds-core `,
});
banner.raws.left = '';
banner.raws.right = '';

// After @charset, which must stay first.
const charset = root.first?.name === 'charset' ? root.first : null;
if (charset) charset.after(banner);
else root.prepend(banner);
},
};
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@
"./scss": "./src/scss/hds.scss",
"./scss/uswds": "./src/scss/hds-uswds.scss",
"./scss/dataviz": "./src/scss/hds-dataviz.scss",
"./assets": "./dist/assets/"
"./js/uswds": "./dist/js/uswds.min.js",
"./assets/*": "./dist/assets/*"
},
"files": [
"dist/",
"src/scss/",
"src/assets/"
"src/scss/"
],
"scripts": {
"sass:hds": "sass src/scss/hds.scss dist/css/hds.css --load-path=node_modules/@uswds/uswds/packages --load-path=src/scss --source-map --style=expanded --quiet-deps",
Expand Down
5 changes: 5 additions & 0 deletions postcss.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@ import autoprefixer from 'autoprefixer';
import discardComments from 'postcss-discard-comments';
import cssnano from 'cssnano';

import hdsStamp from './.config/postcss-hds-stamp.mjs';

const plugins = [autoprefixer(), discardComments()];

if (process.env.MINIFY === 'true' || process.env.NODE_ENV === 'production') {
plugins.push(cssnano({ preset: 'default' }));
}

// Last: the version banner must outlive comment discarding and minification.
plugins.push(hdsStamp());

export default { plugins };
2 changes: 2 additions & 0 deletions public-api.snapshot.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ src/scss/hds-uswds.scss
--hds-summary-border-radius
--hds-summary-border-width
--hds-table-border-width
--hds-uswds-version
--hds-version

## Custom Properties (hds-dataviz.min.css)
--hds-dataviz-color-cat-1
Expand Down
16 changes: 6 additions & 10 deletions stories/guides/NoBuildEnvironments.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Before using this guide, confirm your site is approved to remain standalone. See

## Add the stylesheet and scripts

Download the HDS Core distribution from GitHub or install via npm, then add these to your HTML:
First [get the package](?path=/docs/overview-installation--docs#get-the-package): download the dist zip or install via npm, and verify the download. Then add these to your HTML:

```html
<head>
Expand All @@ -28,17 +28,13 @@ Download the HDS Core distribution from GitHub or install via npm, then add thes

USWDS 3.x is written in vanilla JavaScript and does not conflict with jQuery. If your legacy site depends on older versions of jQuery, the USWDS scripts run safely alongside it.

### Verify the download before you copy it onto your server
A copied `dist/` keeps no record of what you installed, so the stylesheet carries its own version. Read it at runtime to confirm what is deployed:

npm verifies package integrity for you. If you download the dist zip from the [Releases page](https://github.com/nasa/hds-core/releases) instead, that check is yours to run. GitHub displays a SHA-256 digest under the zip asset on the release, and the release notes repeat the same digest under "Verify your download".

Hash your download and confirm it matches the digest on the release before extracting:

```sh
sha256sum hds-core-*-dist.zip
```js
getComputedStyle(document.documentElement).getPropertyValue('--hds-version').trim(); // 0.9.0
```

On macOS, use `shasum -a 256` instead. If the two digests differ, the file was corrupted or tampered with in transit. Do not deploy it: re-download, and if it still fails, [open an issue](https://github.com/nasa/hds-core/issues).
See [Installation](?path=/docs/overview-installation--docs#which-version-am-i-running) for the full version and provenance details.

## Use HDS tokens in your existing CSS

Expand Down Expand Up @@ -135,7 +131,7 @@ Fixed-width containers break on mobile and fail responsive layout requirements.
</div>
```

> These grid and layout classes require loading `hds-uswds.min.css` alongside `hds.min.css`. This is a temporary migration step as you modernize your markup, the goal is to move toward CSS Grid and Flexbox natively, which removes the need for utility classes entirely.
> These grid and layout classes are included in `hds.min.css`, so no extra file is needed. (The optional `hds-uswds.min.css` bundle adds spacing, color, and other utility classes like `.padding-2` or `.text-primary`, not grid.) Grid is a temporary migration step: as you modernize your markup, the goal is to move toward CSS Grid and Flexbox natively, which removes the need for utility classes entirely.

### Semantics: fix inaccessible markup

Expand Down
5 changes: 2 additions & 3 deletions stories/guides/ReactSetup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ export default defineConfig({
viteStaticCopy({
targets: [
// HDS fonts (DM Mono, Inter) — lands at dist/assets/fonts/
{ src: 'node_modules/@nasa-hds/core/src/assets/fonts', dest: 'assets', rename: { stripBase: 5 } },
{ src: 'node_modules/@nasa-hds/core/dist/assets/fonts', dest: 'assets', rename: { stripBase: 5 } },
// HDS icon SVGs (accordion, table sort, external link, form error)
{ src: 'node_modules/@nasa-hds/core/src/assets/img', dest: 'assets', rename: { stripBase: 5 } },
{ src: 'node_modules/@nasa-hds/core/dist/assets/img', dest: 'assets', rename: { stripBase: 5 } },
// Public Sans — from USWDS — lands at dist/assets/fonts/public-sans/
{ src: 'node_modules/@uswds/uswds/dist/fonts/public-sans', dest: 'assets/fonts', rename: { stripBase: 5 } },
// USWDS images (checkboxes, radio indicators, etc.)
Expand All @@ -79,7 +79,6 @@ export default defineConfig({
preprocessorOptions: {
scss: {
loadPaths: ['node_modules/@uswds/uswds/packages', 'node_modules/@nasa-hds/core/src/scss'],
loadPaths: ['node_modules/@uswds/uswds/packages', 'node_modules/@nasa-hds/core/src/scss'],
},
},
},
Expand Down
Loading