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
60 changes: 17 additions & 43 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
name: CI

# The gate on every change, on a clean Linux machine of a fixed release, so a new image never changes a result unasked: the tests, the tests in a real browser, the bundle, the package project's build with no warnings, and the format check.
# The gate on every push but main's, which promotion fast-forwards to a commit that passed on candidate, and on every pull request, on a clean Linux machine of a fixed release, so a new image never changes a result unasked: the tests, the tests in a real browser, the bundle, the package project's build with no warnings, and the format check. A push to candidate runs the full gate, which packs the NuGet package and verifies it as consumers install it, and keeps the packages for the release to publish.
on:
push:
branches: [main]
branches-ignore: [main]
pull_request:

permissions:
contents: read

# A newer push to a pull request supersedes the older run; every commit on main keeps its own result.
# A newer push to a pull request supersedes the older run; every commit on a branch keeps its own result.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
Expand All @@ -18,7 +18,7 @@ concurrency:
env:
PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/.playwright

# DOMQL builds against the Nexo release nexo.release pins, the tree of its tag, taken from a checkout beside its own, formaui-net.Nexo beside formaui-net.DOMQL, until it consumes Nexo's published package, so each job checks out both, Nexo at that tag.
# DOMQL builds against the Nexo release nexo.release pins, the tree of its tag, taken from a checkout beside its own, formaui-net.Nexo beside formaui-net.DOMQL, until it consumes Nexo's published package, so the job checks out both, Nexo at that tag.
defaults:
run:
working-directory: formaui-net.DOMQL
Expand All @@ -28,6 +28,8 @@ jobs:
gate:
name: Gate
runs-on: ubuntu-24.04
env:
CANDIDATE: ${{ github.event_name == 'push' && github.ref == 'refs/heads/candidate' }}
steps:
# The gated commit alone, since the sources declare every version and nothing reads the history.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down Expand Up @@ -73,50 +75,22 @@ jobs:
npx --prefix tests playwright install-deps chromium firefox webkit

- name: Gate
if: env.CANDIDATE != 'true'
shell: pwsh
run: ./build.ps1 -Browser

package:
name: Package
needs: gate
runs-on: ubuntu-24.04
steps:
# The gated commit alone, since the sources declare every version and nothing reads the history.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: formaui-net.DOMQL

# The tag of the Nexo release DOMQL builds against, which nexo.release pins.
- name: Read the pinned Nexo release
id: nexo
run: echo "tag=v$(tr -d '[:space:]' < nexo.release)" >> "$GITHUB_OUTPUT"

# Nexo's whole history, since DOMQL's documents link to commits a record of the past names, which the link test reads.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: FormaUI/Nexo
ref: ${{ steps.nexo.outputs.tag }}
path: formaui-net.Nexo
fetch-depth: 0

- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: 24
cache: npm
cache-dependency-path: |
formaui-net.DOMQL/package-lock.json
formaui-net.DOMQL/tests/package-lock.json

- uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: formaui-net.DOMQL/nuget/global.json

- name: Pack
- name: Full gate
if: env.CANDIDATE == 'true'
shell: pwsh
run: ./publish.ps1
run: ./build.ps1 -Browser -Full

# The packages the full gate built and verified, under the name the release's checks read them by, kept as long as GitHub allows.
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
if: env.CANDIDATE == 'true'
with:
name: package
path: formaui-net.DOMQL/artifacts/*.nupkg
name: packages
path: |
formaui-net.DOMQL/artifacts/*.nupkg
formaui-net.DOMQL/artifacts/*.snupkg
if-no-files-found: error
retention-days: 90
30 changes: 30 additions & 0 deletions .github/workflows/promotion.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Promotion

# The promotion check on every pull request into main, from the FormaUI Versioning release DOMQL follows: it comes from candidate, ci.yml's full gate passed on its head commit and kept the packages, its version is higher than every release's and on no feed, and its changelog entry is dated.
on:
pull_request:
branches: [main]
types: [opened, edited, reopened, synchronize]

permissions:
contents: read
actions: read
pull-requests: read

# Each action is pinned to the commit of the release named in its comment.
jobs:
promotion:
name: Promotion
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha }}

# The runtime version src/Versions.mjs declares, which the package carries.
- uses: FormaUI/Versioning/actions/promotion-check@68ff74cadbe94084384d29be93466713fd989b53 # v1.0.0-preview.1
with:
gate-workflow: ci.yml
version-command: >-
[regex]::Match((Get-Content src/Versions.mjs -Raw), "runtime = '([^']+)'").Groups[1].Value
packages-artifact: packages
66 changes: 66 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Release

# A release tag's push: the release check of the FormaUI Versioning release DOMQL follows, then the packages candidate's full gate built, attached to the tag's GitHub release with their digests, and published from there to nuget.org through trusted publishing. A run that fails runs again for the same tag, publishing what the feed lacks. DOMQL publishes no npm package yet.
on:
push:
tags: ['v*']

permissions:
contents: read

# Each action is pinned to the commit of the release named in its comment.
jobs:
release:
name: Release
runs-on: ubuntu-24.04
# Only a v* tag deploys to the release environment, and the feed's trusted-publishing policy names it, so only a release tag's run publishes.
environment: release
permissions:
contents: write
actions: read
pull-requests: read
id-token: write
steps:
# The whole history, so the check finds the tag's commit in main's.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

# The runtime version src/Versions.mjs declares, which the package carries.
- id: check
uses: FormaUI/Versioning/actions/release-check@68ff74cadbe94084384d29be93466713fd989b53 # v1.0.0-preview.1
with:
gate-workflow: ci.yml
version-command: >-
[regex]::Match((Get-Content src/Versions.mjs -Raw), "runtime = '([^']+)'").Groups[1].Value
packages-artifact: packages

- id: packages
uses: FormaUI/Versioning/actions/release-packages@68ff74cadbe94084384d29be93466713fd989b53 # v1.0.0-preview.1
with:
gate-run-id: ${{ steps.check.outputs.gate-run-id }}
packages-artifact: packages
name: DOMQL

- uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: nuget/global.json

# A short-lived nuget.org key, for the account NUGET_USER names, whose trusted-publishing policy names this workflow.
- id: nuget
uses: NuGet/login@8d196754b4036150537f80ac539e15c2f1028841 # v1.2.0
with:
user: ${{ vars.NUGET_USER }}

# The package and its symbols, past a version nuget.org holds already.
- name: Publish to nuget.org
shell: pwsh
env:
NUGET_API_KEY: ${{ steps.nuget.outputs.NUGET_API_KEY }}
PACKAGES: ${{ steps.packages.outputs.directory }}
VERSION: ${{ steps.check.outputs.version }}
run: |
dotnet nuget push (Join-Path $env:PACKAGES "formaui-net.DOMQL.$env:VERSION.nupkg") --api-key $env:NUGET_API_KEY --source https://api.nuget.org/v3/index.json --skip-duplicate
if ($LASTEXITCODE -ne 0) {
throw 'Publishing to nuget.org failed.'
}
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ nuget/bin/
nuget/obj/
artifacts/

# The bundle that publish.ps1 makes from src/.
# What an IDE builds of the package consumer the full gate copies out of the repository.
scripts/packages/*/bin/
scripts/packages/*/obj/

# The bundle that build.ps1 makes from src/.
nuget/wwwroot/

# The browser CI installs for the browser tests.
Expand Down
11 changes: 6 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ Each release of DOMQL's packages, newest first. The NuGet package `formaui-net.D
- **An entry is dated when its release is cut,** and reads *Unreleased* until then. [Cutting a release](CONTRIBUTING.md#cut-a-release) tags its commit, and its packages are published from that tag.
- **A change a caller can notice** is listed in the newest entry while it is unreleased. Once it is released, the change opens the next version's entry, and the sources declare that version in the same commit.

<a id="v1-0-0-beta-1"></a>
<a id="v1-0-0-preview-1"></a>

## `1.0.0-beta.1`
## `1.0.0-preview.1`

*Unreleased · specification `1.0.0-beta.2` · Nexo language `1.0.0-beta.41` · definition format 38*
*November 5, 2026 · specification `1.0.0-preview.1` · Nexo language `1.0.0-preview.1` · definition format 38*

- The first beta, and the first release. The [version history](VERSION-HISTORY.md) records what came before it.
- Runs on Nexo's language `1.0.0-beta.41`, from Nexo's release `1.0.0-beta.2`, as the [version history](VERSION-HISTORY.md#v1-0-0-beta-2) sets out: `and` and `or` typed where their value is used, a selection into a dictionary's `entries` and a pair's `key` and `value`, a module's maintained members declaring nullable results, and the members that make a value of their receiver called as functions, `round()` and `trim()` among them, among the rest.
- The first preview, and the first release, as [FormaUI Versioning's stages](https://github.com/FormaUI/Versioning/blob/v1.0.0-preview.1/docs/versions.md#stages) name it: the runtime and the specification take `1.0.0-preview.1`, with the beta's promise. The [version history](VERSION-HISTORY.md) records what came before it.
- The NuGet package links its release notes to its changelog entry at its tag, records its repository and commit through Source Link, and ships its symbols beside it as a `.snupkg`. It no longer holds the build's `global.json`, which it delivered to a consumer as content.
- Runs on Nexo's language `1.0.0-preview.1`, from Nexo's release `1.0.0-preview.1`, as the [version history](VERSION-HISTORY.md#v1-0-0-preview-1) sets out: `and` and `or` typed where their value is used, a selection into a dictionary's `entries` and a pair's `key` and `value`, a module's maintained members declaring nullable results, the members that make a value of their receiver called as functions, `round()` and `trim()` among them, and an empty line before a body's `return` in `domql.format`'s text, among the rest.
- Each state DOMQL declares is a Boolean property, read without a call, `it.checked`, where it was a function, `it.checked()`. An element's `hover` and `focus`, the document's `focus`, and the window's `share` and `clipboard` are `hovered`, `focused`, `canShare` and `hasClipboard`.
- Each built-in execution is named by its verb: `takeFocus`, `writeClipboard`, `readClipboard`, `writeValue` and `writeSelection` are `focus`, `writeToClipboard`, `readFromClipboard`, `replaceValue` and `select`, and `writeMuted(muted)` and `writeIndeterminate(indeterminate)` are `mute()` and `unmute()`, and `markIndeterminate()` and `clearIndeterminate()`.
- A watch of `focused`, `focusWithin`, `activeElement` or a selector testing focus follows the focus moving inside an open shadow root, and the focused element removed, in every engine.
Expand Down
Loading