Shape Constraint

Schema Definition

Schema definition for https://pagelove.org/ShapeConstraint type
Name Type Cardinality Description
resource https://schema.org/Text 0..n Optionally, the resource name this shape is applied to
selector https://schema.org/Text 0..n Optionally, a CSS selector defining the constrained element
constraint https://schema.org/Text 1..n A CSS selector defining the constraint

Description

ShapeConstraint is an HTML microdata schema used by Pagelove to perform structural validation of document modifications using standard CSS selectors.

Rather than validating data using a separate schema language (such as SHACL or JSON Schema), Pagelove allows constraints to be expressed directly in HTML, using selectors that operate on the DOM being written.

A ShapeConstraint answers the question:

When something is modified, what structure must exist for that modification to be accepted?

What Shape Constraints do

When present in a Pagelove site, ShapeConstraint declarations participate in request processing for any HTTP method that mutates state (for example POST, PUT, or DELETE).

A constraint may apply to:

If a constraint is violated, the modification is rejected.

Properties

resource (optional)

One or more resource names or path patterns the constraint applies to.

If omitted, the constraint applies globally.

Examples:

selector (optional)

One or more CSS selectors identifying the elements being constrained.

If omitted, the selector is treated as :root (the document as a whole)

The selector is matched against the element(s) targeted by the incoming modification.

constraint (required, repeatable)

Each constraint is a CSS selector that must match within the modified element’s subtree.

All listed constraints must succeed for the modification to be accepted.

Validation model (informal)

For each incoming mutating request:

  1. Identify all ShapeConstraint declarations whose resource matches the request path (or which are global).
  2. For each matching constraint:
    • Check whether the request target element matches the constraint’s selector (or :root).
    • If it does, evaluate every constraint selector against the proposed modified DOM fragment.
  3. If any selector fails to match:
    • Reject the request with HTTP 422 Unprocessable Content.
  4. Otherwise:
    • Apply the modification normally.

HTTP error behaviour

If one or more constraints fail during request processing, the server MUST respond with:

422 Unprocessable Content

No partial modification is applied.

Example

The following constraint enforces that any modified list item representing a User must contain both username and email microdata properties.

<div itemscope itemtype="https://pagelove.org/ShapeConstraint">

  <p>
    When the selector <code itemprop="selector">li[itemtype*=User]</code>
    matches, the following elements must be present:
  </p>

  <ul>
    <li itemprop="constraint"><code>:has([itemprop="username"])</code></li>
    <li itemprop="constraint"><code>:has([itemprop="email"])</code></li>
  </ul>

</div>

Meaning

This declaration means:

For any POST or PUT that modifies an element matching li[itemtype*=User] The modified DOM fragment must contain: - [itemprop="username"] - [itemprop="email"]

If either is missing, the request is rejected with 422 Unprocessable Content.

For any DELETE, find the closest ancestor that matches li[itemtype*=User]. If there is one, then it must contain: - [itemprop="username"] - [itemprop="email"]

If either is missing, the request is rejected with 409 Conflict.