type: string, format: uri|uri-reference now support contentMediaType: image/*|video/* and x-allowed-schemes: [http, https, ftp, public, …], allowing to drop unsustainably complex patterns
Previously, SDC (and code component) props that expected an image or a video needed to be matched against Drupal core's FileExtension validation constraint, which necessarily requires translating from/to two wildly different representations: pattern (aka a regex!) vs a list of file extensions.
The problem: the list of file extensions is hardcoded. Which means customizations to the list of allowed image types would be a problem. Recently, AVIF support landed in #3372932: [Meta] High-performance images (nearly) out of the box, which shows how likely this is to happen over time.
Worse, validating file extensions requires validating the end of the given URI (but must ignore query strings and fragments), but validating URI schemes ("protocols") requires validating the start of the given URI. So: very complex (and brittle!) combining of regular expressions is necessary for shape matching to work completely.
- Old
-
"stream-wrapper-image-uri": { "title": "Stream wrapper image URI", "type": "string", "format": "uri", "pattern": "^(?!https?://)[\\w\\-]+://.*\\.([Pp][Nn][Gg]|[Gg][Ii][Ff]|[Jj][Pp][Gg]|[Jj][Pp][Ee][Gg]|[Ww][Ee][Bb][Pp]|[Aa][Vv][Ii][Ff])(\\?.*)?(#.*)?$" }, "image-uri": { "title": "Image URL", "type": "string", "format": "uri-reference", "pattern": "^(/|https?://)?.*\\.([Pp][Nn][Gg]|[Gg][Ii][Ff]|[Jj][Pp][Gg]|[Jj][Pp][Ee][Gg]|[Ww][Ee][Bb][Pp]|[Aa][Vv][Ii][Ff])(\\?.*)?(#.*)?$" }, … "video": { "title": "video", "type": "object", "required": ["src"], "properties": { "src": { "title": "Video URL", "type": "string", "format": "uri-reference", "pattern": "^(/|https?://)?.*\\.([Mm][Pp]4)(\\?.*)?(#.*)?$" }, "poster": { "title": "Poster image URL", "$ref": "json-schema-definitions://canvas.module/image-uri" } } }, - The old code dates back to April 2024, _before_ we had even started using d.o issues. This is some of the oldest code in Canvas and dates back to the
research__data_modelPoC research branch.Note: this follows a 2017 best practice!
- Interim
- No more file extensions in
pattern. But still some regular expressions 🙈"stream-wrapper-image-uri": { "title": "Stream wrapper image URI", "type": "string", "format": "uri", "contentMediaType": "image/*", "pattern": "^(?!https?://)[\\w\\-]+://" }, "image-uri": { "title": "Image URL", "type": "string", "format": "uri-reference", "contentMediaType": "image/*", "pattern": "^(/|https?://)?(?!.*\\://)[^\\s]+$" }, … "video": { "title": "video", "type": "object", "required": ["src"], "properties": { "src": { "title": "Video URL", "type": "string", "format": "uri-reference", "contentMediaType": "video/*", "pattern": "^(/|https?://)?(?!.*\\://)[^\\s]+$" }, "poster": { "title": "Poster image URL", "$ref": "json-schema-definitions://canvas.module/image-uri" } } }, - Now
- No more
patternat all: much simpler, much more reliable! Described at #3530351-22: Decouple image+video (URI) shape matching from specific image+video file types/extensions. This follows JSON Schema best practices: https://json-schema.org/blog/posts/custom-annotations-will-continue"stream-wrapper-image-uri": { "title": "Stream wrapper image URI", "type": "string", "format": "uri", "contentMediaType": "image/*", "x-allowed-schemes": ["public"], }, "image-uri": { "title": "Image URL", "type": "string", "format": "uri-reference", "contentMediaType": "image/*", "x-allowed-schemes": ["http", "https"], }, … "video": { "title": "video", "type": "object", "required": ["src"], "properties": { "src": { "title": "Video URL", "type": "string", "format": "uri-reference", "contentMediaType": "video/*", "x-allowed-schemes": ["http", "https"], }, "poster": { "title": "Poster image URL", "$ref": "json-schema-definitions://canvas.module/image-uri" } } },
Impact for SDC maintainers
🎉 None breaking, only new possibilities!
New possibility: indicate that a particular URL must use the https URI scheme, to ensure no eavesdropping on visitors is possible.
ℹ️ Note: the JSON Schema validator that Drupal core uses to validate the inputs that are passed to an SDC has been decorated to detect invalid URIs being passed, e.g. one using the ftp:// scheme instead of the expected https://. This means you'll get precise feedback 👍
Any SDC using props whose shapes use $refs will be automatically updated (!!!):
$ref: json-schema-definitions://canvas.module/image$ref: json-schema-definitions://canvas.module/video$ref: json-schema-definitions://canvas.module/image-uri$ref: json-schema-definitions://canvas.module/stream-wrapper-image-uri
That should be every SDC that was using images and videos (the first 2).
The latter 2 did NOT result in the expected UX before this change (…/image-uri and …/stream-wrapper-image-uri), but now they do work.
(Notably, the various "card using a specific kind of image" test SDCs that #3535453: Create an Image SDC that can be included by other SDCs introduced now started working as intended.)
Impact for hook_storage_prop_shape_alter() implementations
🎉 None! Existing implementations that target either of the above $refs will continue to work as-is.
⚠️ However, it is recommended to not only target json-schema-definitions://canvas.module/image (which is src+alt+width+height), but also json-schema-definitions://canvas.module/image-uri (which is just src) and json-schema-definitions://canvas.module/stream-wrapper-image-uri (which is just src, but not yet browser-renderable). That way, all possible uses of images are covered. Similar for videos.