Skip to content

Conversation

@kfranqueiro
Copy link
Contributor

@kfranqueiro kfranqueiro commented Nov 25, 2025

This adds support to spec-generator for generating Bikeshed specs and issue lists, in a way that provides near-parity with the features of the CSSWG API.

Functionality included:

  • Setting what event level to die on (via HTML form or die-on)
  • Overriding the date in specs (via HTML form or md-date)
  • Setting the Prepare for TR flag (via HTML form or md-prepare-for-tr)
  • Arbitrary metadata overrides (via md-<key>)
  • Specifying a URL or uploading a standalone or tar file for both specs and issue lists
    • This is particularly notable for the case of issue list URLs, as the CLI and CSSWG API do not support this
  • Expandable help section with details on the HTTP API

The most notable thing that isn't included is an equivalent to the CSSWG API's output=err, which I'd like to work on separately after this, to avoid making this PR even bigger.

The diff will be rather large, because I moved the majority of the code that had been in server.ts into generator/respec.ts in the process, as a lot of it was respec-specific. Now generator/bikeshed.ts and generator/respec.ts each export a similar API which server.ts calls after validating parameters, depending on the type parameter.

Other changes included in this PR:

  • Carries over die-on support to ReSpec, to maximize the amount of shared fields between the available generators
  • Carries over md-date and md-<key> support to ReSpec, to make it possible to override respecConfig properties even in case of file upload, which previously wasn't possible
  • Makes start function in server.ts async, to wait until the server is listening
  • Reformats all TS files and index.html to 2-space indent (from 4) to match other repos and default Prettier settings; since this PR results in a lot of changed lines already due to most code being added or relocated, it made sense to tackle this now as well (already discussed with Denis)
    • Note: I tried running index.html through Prettier in the process, but ended up re-excluding it because of a couple of non-configurable decisions Prettier makes that I disagree with, primarily the inclusion of self-closing tags
    • Also note this means that hiding whitespace in the PR diff will make it at least a little bit less noisy
  • Updates npm run watch to also restart on HTML changes
  • Updates npm test to correctly run all tests - and there are many more now, including tests across GET, POST, and POST with query string parameters, wherever applicable

This is what's used in other w3c repos I've encountered.
Now is a good time to switch, since this PR is already heavily touching
all of the TS code in the repo anyway.
- Adds md-<key> and die-on support to ReSpec
- Expands tests and fixes test script to actually run all of them
- Updates watch script to also restart on HTML change
- TODO: Add die-on tests for ReSpec
@kfranqueiro kfranqueiro requested a review from deniak November 25, 2025 14:20
@kfranqueiro kfranqueiro requested a review from deniak December 2, 2025 14:04
Comment on lines 46 to 48
throw new SpecGeneratorError(
`Did not generate, due to errors exceeding the allowed error level.`,
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a way to expose the errors/warnings (or their counts) even with dieOn?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call-out; I've moved this code so it can share the same flow that currently produces headers regarding number of errors/warnings.

I want to do a future pass to actually include all errors when a run fails for this reason (for both ReSpec and Bikeshed) and to honor something like the output=err parameter that exists in the CSSWG API for Bikeshed, to allow seeing messages even if processing succeeds.

const extract = tar.extract();
const uploadPath = await mkdtemp("uploads/");

return new Promise((resolve, reject) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: if we're using Node.js v22+, we can use Promise.withResolvers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the tip; we currently run tests for v20, v22, and v24, which would preclude using this.

I'm +0 on it; I kind of like conceptually limiting the scope of resolve and reject. The instances in this PR wouldn't particularly benefit from the scope-collapsing of withResolvers (the only let present would still be necessary regardless), though reducing nesting would be nice for the instances in each generator.

@deniak, thoughts on dropping Node 20 from test.yml? (I would probably want to do it separately from this PR.)

type="radio"
name="type"
value="respec"
checked
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small enhancement: If url parameter has ?type set, we can check the right radio buttons with script.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a use case for this enhancement? I ask because this would expose multiple edge cases if the user were to change the Document type choice after loading this way:

  • Doing this client-side would override any previous user input within these radio buttons if the user were to refresh the page or revisit the form via browser history
    • Doing this server-side would avoid this, but would involve adding more complexity and dependencies to the Express setup (which I had considered doing earlier in this PR, but later decided to avoid when merging back to a single page)
  • GET parameters currently override POST parameters if both are present; I'd need to flip this, otherwise the form submission (which uses action="" to work regardless of base path) will break if a user changes the Document type, then performs a file upload with type in the URL
    • Changing this might be fine; many curl use cases found across GitHub use GET parameters with a POST request, but are unlikely to define the same parameter both ways

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants