@webstir-io/module-contract 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The wire protocol between the client-nav feature and the backend runtime. Constants only, so a
3
+ * browser bundle can import them without the rest of the contract.
4
+ */
5
+ export declare const CLIENT_NAV_HEADERS: {
6
+ /** Sent on every request client-nav makes itself. */
7
+ readonly request: 'x-webstir-client-nav';
8
+ /**
9
+ * Sent when client-nav can follow a redirect itself: the backend then answers a redirect with
10
+ * 204 and `location` instead of 3xx, so the destination keeps its #fragment.
11
+ */
12
+ readonly acceptLocation: 'x-webstir-accept-location';
13
+ /** Where to go next, in place of a redirect's Location. */
14
+ readonly location: 'x-webstir-location';
15
+ /** Identifies one form submission, so the same post sent again gets the first answer. */
16
+ readonly submission: 'x-webstir-submission';
17
+ };
18
+ /** The form field carrying the submission id when client-nav falls back to a normal post. */
19
+ export declare const CLIENT_NAV_SUBMISSION_FIELD = "_webstir_submission";
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The wire protocol between the client-nav feature and the backend runtime. Constants only, so a
3
+ * browser bundle can import them without the rest of the contract.
4
+ */
5
+ export const CLIENT_NAV_HEADERS = {
6
+ /** Sent on every request client-nav makes itself. */
7
+ request: 'x-webstir-client-nav',
8
+ /**
9
+ * Sent when client-nav can follow a redirect itself: the backend then answers a redirect with
10
+ * 204 and `location` instead of 3xx, so the destination keeps its #fragment.
11
+ */
12
+ acceptLocation: 'x-webstir-accept-location',
13
+ /** Where to go next, in place of a redirect's Location. */
14
+ location: 'x-webstir-location',
15
+ /** Identifies one form submission, so the same post sent again gets the first answer. */
16
+ submission: 'x-webstir-submission',
17
+ };
18
+ /** The form field carrying the submission id when client-nav falls back to a normal post. */
19
+ export const CLIENT_NAV_SUBMISSION_FIELD = '_webstir_submission';
package/dist/index.d.ts CHANGED
@@ -4554,3 +4554,4 @@ export { RENDER_PROGRAM_FILE, RENDER_PROGRAM_VERSION, renderFlashMessageSchema,
4554
4554
  export type { RenderFlashMessage, RenderNode, RenderPath, RenderProgram, RenderSourceLocation, } from './render-program.js';
4555
4555
  export { executeRenderProgram, programUsesCsrf, readRenderProgram, RENDER_CSRF_FIELD, RenderProgramError, prepareViewData, schemaDeclaresField, } from './render-execute.js';
4556
4556
  export type { ExecuteRenderProgramOptions, PreparedViewData } from './render-execute.js';
4557
+ export { CLIENT_NAV_HEADERS, CLIENT_NAV_SUBMISSION_FIELD } from './client-nav.js';
package/dist/index.js CHANGED
@@ -234,3 +234,4 @@ export function createModule(definition) {
234
234
  export { fromTsRestRoute, fromTsRestRouter } from './adapters/ts-rest.js';
235
235
  export { RENDER_PROGRAM_FILE, RENDER_PROGRAM_VERSION, renderFlashMessageSchema, renderFlashSchema, renderNodeSchema, renderPathSchema, renderProgramSchema, renderSourceLocationSchema, } from './render-program.js';
236
236
  export { executeRenderProgram, programUsesCsrf, readRenderProgram, RENDER_CSRF_FIELD, RenderProgramError, prepareViewData, schemaDeclaresField, } from './render-execute.js';
237
+ export { CLIENT_NAV_HEADERS, CLIENT_NAV_SUBMISSION_FIELD } from './client-nav.js';
@@ -2,6 +2,27 @@ import { RENDER_PROGRAM_VERSION, } from './render-program.js';
2
2
  export const RENDER_CSRF_FIELD = '_csrf';
3
3
  const SAFE_URL_SCHEMES = new Set(['http', 'https', 'mailto', 'tel']);
4
4
  const BLOCKED_URL = 'about:invalid';
5
+ // ARIA attributes whose values include the tokens "true" and "false" (WAI-ARIA 1.2). The rest take
6
+ // text or ids, where false still leaves the attribute out.
7
+ const ARIA_TRUE_FALSE = new Set([
8
+ 'aria-atomic',
9
+ 'aria-busy',
10
+ 'aria-checked',
11
+ 'aria-current',
12
+ 'aria-disabled',
13
+ 'aria-expanded',
14
+ 'aria-grabbed',
15
+ 'aria-haspopup',
16
+ 'aria-hidden',
17
+ 'aria-invalid',
18
+ 'aria-modal',
19
+ 'aria-multiline',
20
+ 'aria-multiselectable',
21
+ 'aria-pressed',
22
+ 'aria-readonly',
23
+ 'aria-required',
24
+ 'aria-selected',
25
+ ]);
5
26
  export class RenderProgramError extends Error {
6
27
  loc;
7
28
  constructor(loc, message) {
@@ -52,7 +73,11 @@ function run(nodes, data, scopes, options, out) {
52
73
  }
53
74
  case 'attr': {
54
75
  const value = read(node.path, data, scopes);
55
- if (value === true) {
76
+ // ARIA states are the words "true" and "false", not an attribute's presence.
77
+ if (typeof value === 'boolean' && ARIA_TRUE_FALSE.has(node.name.toLowerCase())) {
78
+ out.push(` ${node.name}="${value}"`);
79
+ }
80
+ else if (value === true) {
56
81
  out.push(` ${node.name}`);
57
82
  }
58
83
  else if (value !== false && value !== null && value !== undefined) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webstir-io/module-contract",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Public contract definitions for Webstir frontend and backend module providers.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -11,6 +11,11 @@
11
11
  "import": "./dist/index.js",
12
12
  "default": "./dist/index.js"
13
13
  },
14
+ "./client-nav": {
15
+ "types": "./dist/client-nav.d.ts",
16
+ "import": "./dist/client-nav.js",
17
+ "default": "./dist/client-nav.js"
18
+ },
14
19
  "./ts-rest": {
15
20
  "types": "./dist/adapters/ts-rest.d.ts",
16
21
  "import": "./dist/adapters/ts-rest.js",