Skip to content

Commit

Permalink
feat(validate/webidl): add Web IDL validator (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
tidoust authored Sep 10, 2021
1 parent 4b53b84 commit e228dcc
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 3 deletions.
13 changes: 13 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ inputs:
VALIDATE_MARKUP:
description: Validate markup
default: true
VALIDATE_WEBIDL:
description: Validate Web IDL
default: true
GH_PAGES_BRANCH:
description: Provide a branch name to deploy to GitHub pages.
GH_PAGES_BUILD_OVERRIDE:
Expand Down Expand Up @@ -110,6 +113,16 @@ runs:
INPUTS_VALIDATE_MARKUP: ${{ fromJson(steps.prepare.outputs.validate).markup }}
OUTPUTS_BUILD: ${{ toJson(fromJson(steps.build.outputs.w3c)) }}

- name: Validate Web IDL
run: |
echo "::group::Validate Web IDL"
node --enable-source-maps ${{ github.action_path }}/src/validate-webidl.js
echo "::endgroup::"
shell: bash
env:
INPUTS_VALIDATE_WEBIDL: ${{ fromJson(steps.prepare.outputs.validate).webidl }}
OUTPUTS_BUILD: ${{ toJson(fromJson(steps.build.outputs.w3c)) }}

- name: Deploy to GitHub pages
run: |
echo "::group::Deploy to GitHub pages"
Expand Down
4 changes: 2 additions & 2 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
### Selectively enable/disable validators
By default, both hyperlink and markup validators are enabled.
By default, both markup and Web IDL validators are enabled.
```yaml
# Create a file called .github/workflows/auto-publish.yml
Expand All @@ -35,7 +35,7 @@ jobs:
- uses: actions/checkout@v2
- uses: w3c/spec-prod@v2
with:
VALIDATE_LINKS: false
VALIDATE_WEBIDL: false
VALIDATE_MARKUP: true
```
Expand Down
12 changes: 12 additions & 0 deletions docs/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,18 @@ The Action will try to make use of metadata/config from previously published ver
# respec -s index.html?specStatus=WD&shortName=my-custom-shortname… -o OUTPUT
```

## `VALIDATE_WEBIDL`

Whether or not to validate the Web IDL that the spec may define.

Spec authoring tools may already include some level of Web IDL validation but that validation may be restricted to detecting syntax errors. The action also checks additional constraints defined in [Web IDL](https://heycam.github.io/webidl/) such as usage of dictionaries as function parameters or attributes. The action will automatically skip validation if the spec does not define any Web IDL.

Note that the Web IDL validation is restricted to the spec at hand and cannot validate that references to IDL constructs defined in other specs are valid. As such, there may remain IDL errors that can only be detected by tools that look at all specs in combination such as [Webref](https://github.com/w3c/webref)).

**Possible values:** true, false

**Default:** true

## `VALIDATE_LINKS`

Whether or not to check for broken hyperlinks.
Expand Down
3 changes: 2 additions & 1 deletion src/prepare-validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ import { Inputs } from "./prepare.js";
export function validation(inputs: Inputs) {
const links = yesOrNo(inputs.VALIDATE_LINKS) || false;
const markup = yesOrNo(inputs.VALIDATE_MARKUP) || false;
return { links, markup };
const webidl = yesOrNo(inputs.VALIDATE_WEBIDL) || false;
return { links, markup, webidl };
}
1 change: 1 addition & 0 deletions src/prepare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface Inputs {
BUILD_FAIL_ON: string;
VALIDATE_LINKS: string;
VALIDATE_MARKUP: string;
VALIDATE_WEBIDL: string;
GH_PAGES_BRANCH: string;
GH_PAGES_TOKEN: string;
GH_PAGES_BUILD_OVERRIDE: string;
Expand Down
50 changes: 50 additions & 0 deletions src/validate-webidl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { env, exit, install, yesOrNo } from "./utils.js";
import { BuildResult } from "./build.js";
type Input = Pick<BuildResult, "dest" | "file">;

if (module === require.main) {
if (yesOrNo(env("INPUTS_VALIDATE_WEBIDL")) === false) {
exit("Skipped", 0);
}

const input: Input = JSON.parse(env("OUTPUTS_BUILD"));
main(input).catch(err => exit(err.message || "Failed", err.code));
}

export default async function main({ dest, file }: Input) {
console.log(`Validating Web IDL defined in ${file}...`);
await install("reffy");
const { crawlList } = require("reffy/src/cli/crawl-specs");

const fileurl = new URL(file, `file://${dest}/`).href;
const results = await crawlList(
[{ url: fileurl, nightly: { url: fileurl } }],
{ modules: ["idl"] },
);

const idl = results[0]?.idl?.idl;
if (!idl) {
exit("No Web IDL found in spec, skipped validation", 0);
}

await install("webidl2");
const { parse, validate } = require("webidl2");
let errors: { message: string }[] = [];
try {
const tree = parse(idl);
errors = validate(tree);
} catch (error) {
errors = [error];
}
if (!errors.length) {
exit("✅ Looks good! No Web IDL validation errors!", 0);
} else {
console.group("Invalid Web IDL detected:");
for (const error of errors) {
console.log(error.message);
console.log("");
}
console.groupEnd();
exit("❌ Invalid Web IDL detected... please fix the issues above.");
}
}
1 change: 1 addition & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Promise.resolve()
.then(run(require("./build.test.js").default))
.then(run(require("./validate-links.test.js").default))
.then(run(require("./validate-markup.test.js").default))
.then(run(require("./validate-webidl.test.js").default))
.then(run(require("./deploy-gh-pages.test.js").default))
.then(() => {
console.log();
Expand Down
14 changes: 14 additions & 0 deletions test/validate-webidl.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import main from "../src/validate-webidl.js";
import { Outputs } from "./index.test.js";

export default async function validateWebIdl(outputs: Outputs) {
const { webidl: shouldValidate = false } = outputs?.prepare?.validate || {};
if (shouldValidate === false) {
return;
}

const { dest = process.cwd() + ".common", file = "index.html" } =
outputs?.build?.w3c || {};

return await main({ dest, file });
}

0 comments on commit e228dcc

Please sign in to comment.