Skip to content
Merged
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
59 changes: 39 additions & 20 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
@@ -1,33 +1,52 @@
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages

name: Node.js Package

on:
release:
types: [created]
types: [published]
workflow_dispatch:
inputs:
release_tag:
description: "Release tag to publish, for example v1.1.1"
required: true
type: string

permissions:
contents: read

jobs:
build:
publish-npm:
runs-on: ubuntu-latest
env:
RELEASE_TAG: ${{ github.event.inputs.release_tag || github.event.release.tag_name }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Check out release tag
uses: actions/checkout@v4
with:
node-version: 20
- run: npm ci
- run: npm test
ref: ${{ github.event.inputs.release_tag || github.event.release.tag_name }}

publish-npm:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: npm
registry-url: https://registry.npmjs.org/
- run: npm ci
- run: npm publish

- name: Install dependencies
run: npm ci

- name: Validate release tag
run: |
# The published tag is the package artifact contract; fail before npm publish if it drifts.
PACKAGE_VERSION="$(node -p "require('./package.json').version")"
if [ "v${PACKAGE_VERSION}" != "$RELEASE_TAG" ]; then
echo "::error title=Release tag mismatch::Expected v${PACKAGE_VERSION}, got ${RELEASE_TAG}."
exit 1
fi

- name: Verify package
run: npm run check

- name: Publish package to npm
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
node_modules/
.npm-cache/
.tmp/
*.tgz
.superpowers/
output/
Expand Down
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cache=.npm-cache
8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

All notable changes to `layout-style-css` are documented here.

This project follows semantic versioning. The `1.1.0` release is additive and keeps the existing `ly-*` public contract intact.
This project follows semantic versioning. The `1.1.1` release is additive and keeps the existing `ly-*` public contract intact.

## [1.1.0] - 2026-07-05
## [1.1.1] - 2026-07-05

### Added

Expand All @@ -21,14 +21,16 @@ This project follows semantic versioning. The `1.1.0` release is additive and ke
- Reworked the demo mobile controls into a compact drawer so the sticky header does not consume the mobile viewport.
- Expanded the demo to cover app shell, wrappers, split layouts, sidebars, panes, button groups, card grids, card sizes, galleries, carousels, frames, and scroll areas.
- Updated README examples to use exported CSS entrypoints and valid CDN links.
- Updated npm release metadata, package file allowlist, and release verification scripts for the `1.1.0` package.
- Updated npm release metadata, package file allowlist, and release verification scripts for the `1.1.1` package.
- Updated the npm publish workflow to publish from `release.published` events and explicit `workflow_dispatch` tags.

### Fixed

- Fixed README quick-start imports that referenced non-exported paths.
- Fixed malformed UI Style Kit CDN link markup in the README.
- Clarified responsive column utility documentation so class groups do not imply bare numeric class names.
- Preserved GitHub Pages artifact generation with a Pages-root `index.html`.
- Fixed the release automation path so draft releases can be published before the npm workflow runs.

### Security

Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The versioned wiki source lives in this repository so docs can be reviewed with
| [Layout styles](docs/wiki/Layout-Styles.md) | All layout personalities, including F-Pattern, Z-Pattern, Split-Screen, Mondrian, and Synthwave. |
| [UI Style Kit compatibility](docs/wiki/UI-Style-Kit-Compatibility.md) | Prefix aliases and the boundary between structure and visual styling. |
| [Demo and GitHub Pages](docs/wiki/Demo-And-GitHub-Pages.md) | Demo QA, Pages artifact behavior, and deployment setup. |
| [Release and publishing](docs/wiki/Release-And-Publishing.md) | v1.1.0 release checklist, npm verification, and tag guidance. |
| [Release and publishing](docs/wiki/Release-And-Publishing.md) | v1.1.1 release checklist, npm verification, and tag guidance. |
| [Security and support](docs/wiki/Security-And-Support.md) | Security model, supported versions, and reporting path. |
| [Contributing](docs/wiki/Contributing.md) | Local development, CSS rules, and review expectations. |
| [Wiki sidebar source](docs/wiki/_Sidebar.md) | Navigation file for a GitHub Wiki mirror. |
Expand All @@ -41,7 +41,7 @@ Use as a standalone layout system with all styles or just one layout personality

```bash
# Install the full layout system
npm install layout-style-css@1.0.0
npm install layout-style-css@1.1.1
```

Then import whichever CSS entrypoints you need:
Expand All @@ -54,13 +54,13 @@ import "layout-style-css/minimal-saas.css";
Pair with UI Style Kit CSS for a complete layout and visual system. Themes and layouts can mix and match UI styles. Set the vibe with color schemes that offer a range of moods, from minimal to maximal, from Bauhaus to Brutalism.

```bash
npm install layout-style-css@1.0.0 ui-style-kit-css@2.0.1
npm install layout-style-css@1.1.1 ui-style-kit-css@2.0.1
```

Additionally installing Interactive Surface CSS sets you up with a complete reactive layout and surface system.

```bash
npm install layout-style-css@1.0.0 ui-style-kit-css@2.0.1 interactive-surface-css@1.2.5
npm install layout-style-css@1.1.1 ui-style-kit-css@2.0.1 interactive-surface-css@1.2.5
```

## Quick Start
Expand Down Expand Up @@ -592,7 +592,7 @@ The check command builds `dist/`, runs Stylelint, runs contract tests, runs resp
Before publishing:

```bash
npm view layout-style-css@1.1.0 version --json
npm view layout-style-css@1.1.1 version --json
npm run release:verify
npm audit --audit-level=moderate
```
Expand All @@ -602,7 +602,7 @@ Publish and verify:
```bash
npm login
npm publish --access public
npm view layout-style-css@1.1.0
npm view layout-style-css@1.1.1
```

After publish, verify these CDN URLs:
Expand All @@ -612,7 +612,7 @@ https://unpkg.com/layout-style-css@1/dist/layout-style-css.min.css
https://cdn.jsdelivr.net/npm/layout-style-css@1/dist/layout-style-css.min.css
```

Tag the release as `v1.1.0` in `Foscat/layout-style-css`.
Tag the release as `v1.1.1` in `Foscat/layout-style-css`. The npm publish workflow runs when that release is published and can be recovered manually from Actions with `release_tag` set to `v1.1.1`.

## Compatibility

Expand Down
4 changes: 2 additions & 2 deletions docs/wiki/Home.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Layout Style CSS Wiki

Version 1.1.0 documents the professional library contract for `layout-style-css`: install paths, package exports, layout primitives, recipes, UI Style Kit compatibility, demo deployment, security, and release workflow.
Version 1.1.1 documents the professional library contract for `layout-style-css`: install paths, package exports, layout primitives, recipes, UI Style Kit compatibility, demo deployment, security, and release workflow.

## Start Here

Expand All @@ -13,7 +13,7 @@ Version 1.1.0 documents the professional library contract for `layout-style-css`
| [Layout Styles](Layout-Styles.md) | All layout personalities and when to use them. |
| [UI Style Kit Compatibility](UI-Style-Kit-Compatibility.md) | Prefix aliases and ownership boundaries. |
| [Demo And GitHub Pages](Demo-And-GitHub-Pages.md) | Demo QA and Pages deployment. |
| [Release And Publishing](Release-And-Publishing.md) | npm v1.1.0 verification and publish checklist. |
| [Release And Publishing](Release-And-Publishing.md) | npm v1.1.1 verification and publish checklist. |
| [Security And Support](Security-And-Support.md) | Security model, supported versions, and reporting path. |
| [Contributing](Contributing.md) | Contribution workflow and review expectations. |

Expand Down
18 changes: 10 additions & 8 deletions docs/wiki/Release-And-Publishing.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Release And Publishing

This page is the release checklist for `layout-style-css@1.1.0`.
This page is the release checklist for `layout-style-css@1.1.1`.

## Version Contract

- `package.json` version is `1.1.0`.
- `package-lock.json` is synchronized with `1.1.0`.
- `CHANGELOG.md` contains a `1.1.0` entry.
- `package.json` version is `1.1.1`.
- `package-lock.json` is synchronized with `1.1.1`.
- `CHANGELOG.md` contains a `1.1.1` entry.
- README and wiki docs link to the current public API.

## Verification
Expand All @@ -30,7 +30,7 @@ Expected result: every command exits with status `0`. `git diff --check` may pri
Before publishing, confirm npm does not already have the target version:

```bash
npm view layout-style-css@1.1.0 version --json
npm view layout-style-css@1.1.1 version --json
```

Publish:
Expand All @@ -43,18 +43,20 @@ npm publish --access public
Verify:

```bash
npm view layout-style-css@1.1.0
npm view layout-style-css@1.1.1
```

## Tag

Tag the release:

```bash
git tag v1.1.0
git push origin v1.1.0
git tag v1.1.1
git push origin v1.1.1
```

The npm publish workflow runs when the `v1.1.1` GitHub release is published. If the release event needs to be replayed, run the `Node.js Package` workflow manually from the default branch with `release_tag` set to `v1.1.1`.

## GitHub Wiki Mirror

If the repository wiki is enabled, mirror `docs/wiki/*.md` into:
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "layout-style-css",
"version": "1.1.0",
"version": "1.1.1",
"description": "Shell-first CSS layout primitives that complement ui-style-kit-css@2.0.1.",
"type": "module",
"license": "MIT",
Expand Down
8 changes: 7 additions & 1 deletion test/demo-smoke.test.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createReadStream, existsSync } from "node:fs";
import { createReadStream, existsSync, mkdirSync } from "node:fs";
import { createServer } from "node:http";
import { extname, join, normalize, sep } from "node:path";
import { fileURLToPath } from "node:url";
Expand All @@ -7,6 +7,7 @@ import { chromium } from "@playwright/test";

const root = normalize(fileURLToPath(new URL("..", import.meta.url))).replace(/[\\/]$/, "");
const demoPath = join(root, "demo", "index.html");
const testTempDir = join(root, ".tmp", "playwright");
const uiKitCssPath = join(
root,
"node_modules",
Expand All @@ -15,6 +16,11 @@ const uiKitCssPath = join(
"ui-style-kit.with-bridge.min.css"
);

// Keep Playwright artifacts inside the repository workspace for locked-down Windows runners.
mkdirSync(testTempDir, { recursive: true });
process.env.TEMP = testTempDir;
process.env.TMP = testTempDir;

const mimeTypes = new Map([
[".css", "text/css; charset=utf-8"],
[".html", "text/html; charset=utf-8"],
Expand Down
36 changes: 32 additions & 4 deletions test/layout-css-contract.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import assert from "node:assert/strict";
const root = fileURLToPath(new URL("..", import.meta.url));
const dist = join(root, "dist");
const styles = join(root, "styles");
const npmPublishWorkflowPath = join(root, ".github", "workflows", "npm-publish.yml");

const requiredFiles = [
"layout-base.css",
Expand Down Expand Up @@ -622,7 +623,7 @@ assert(!minified.includes("@import"), "Minified bundle must be layout-only and f

const packageJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
assert.equal(packageJson.name, "layout-style-css");
assert.equal(packageJson.version, "1.1.0");
assert.equal(packageJson.version, "1.1.1");
assert.equal(packageJson.license, "MIT");
assert.equal(packageJson.private, undefined);
assert.equal(packageJson.description.includes("ui-style-kit-css@2.0.1"), true);
Expand Down Expand Up @@ -881,8 +882,8 @@ for (const link of readmeLinks.filter(isLocalMarkdownLink)) {
const changelog = readFileSync(join(root, "CHANGELOG.md"), "utf8");
assert(changelog.includes("# Changelog"), "CHANGELOG.md should use a standard changelog heading");
assert(
changelog.includes("## [1.1.0] - 2026-07-05"),
"CHANGELOG.md should describe the 1.1.0 release candidate"
changelog.includes("## [1.1.1] - 2026-07-05"),
"CHANGELOG.md should describe the 1.1.1 release candidate"
);
assert(changelog.includes("F-Pattern"), "CHANGELOG.md should mention the new F-Pattern layout");
assert(changelog.includes("Synthwave"), "CHANGELOG.md should mention the new Synthwave layout");
Expand All @@ -891,7 +892,7 @@ assert(changelog.includes("wiki"), "CHANGELOG.md should mention the new wiki doc

const wikiHome = readFileSync(join(root, "docs/wiki/Home.md"), "utf8");
assert(wikiHome.includes("# Layout Style CSS Wiki"), "Wiki home should use a clear product heading");
assert(wikiHome.includes("Version 1.1.0"), "Wiki home should identify the documented release");
assert(wikiHome.includes("Version 1.1.1"), "Wiki home should identify the documented release");
for (const file of requiredDocumentationFiles.filter((file) => file.startsWith("docs/wiki/"))) {
const content = readFileSync(join(root, file), "utf8");
assert(content.includes("# "), `${file} should include a top-level heading`);
Expand All @@ -905,6 +906,33 @@ for (const file of requiredDocumentationFiles.filter((file) => file.startsWith("
}
}

const npmPublishWorkflow = readFileSync(npmPublishWorkflowPath, "utf8");
assert(
npmPublishWorkflow.includes("types: [published]") && !npmPublishWorkflow.includes("types: [created]"),
"npm publish workflow should publish from public release events, not draft release creation"
);
assert(
npmPublishWorkflow.includes("workflow_dispatch:") &&
npmPublishWorkflow.includes("release_tag:") &&
npmPublishWorkflow.includes('description: "Release tag to publish, for example v1.1.1"'),
"npm publish workflow should expose a manual recovery dispatch with an explicit release tag"
);
assert(
npmPublishWorkflow.includes("ref: ${{ github.event.inputs.release_tag || github.event.release.tag_name }}"),
"npm publish workflow should check out the selected release tag"
);
assert(
npmPublishWorkflow.includes('node-version: 22') &&
npmPublishWorkflow.includes("npm run check") &&
npmPublishWorkflow.includes("npm publish --access public"),
"npm publish workflow should verify and publish with the supported Node runtime"
);
assert(
npmPublishWorkflow.includes('if [ "v${PACKAGE_VERSION}" != "$RELEASE_TAG" ]; then') &&
npmPublishWorkflow.includes("NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}"),
"npm publish workflow should verify tag/package alignment and use the standard npm token secret"
);

const expectedPackFiles = [
"CHANGELOG.md",
"CONTRIBUTING.md",
Expand Down