Problem/Motivation

Strictly speaking, this is not a bug in SDC. But … I just lost an hour over something SDC could've easily warned against:

LOLOL an hour worth of debugging only to find out that SDC prop names may contain dashes but Twig variable names must not: https://github.com/twigphp/Twig/issues/1967 — for example

    {{ test-REQUIRED-string }}

is compiled by Twig to:

        // line 5
        yield $this->extensions['Drupal\Core\Template\TwigExtension']->escapeFilter($this->env, ((($context["test"] ?? null) - ($context["REQUIRED"] ?? null)) - ($context["string"] ?? null)), "html", null, true);

… which means that the DX of SDC is leaving a lot to be desired: if Twig doesn't support this, and SDC supports only Twig, then I expect SDC to not allow this either.

— #3463583-15: Use the `all-props` component for testing form backend + frontend integration

Proposed resolution

  • Restrict prop and slot names to identifiers Twig can actually use: start with a letter or underscore, followed by letters, digits, or underscores.
  • Use JSON Schema's allOf to enforce prop name validation also at the JSON Schema level.

BC concerns: We are more restrictive than before in theory. In practice those props/slots could have never worked with twig.

Remaining tasks

  • Review.
  • Change record.

User interface changes

None.

Introduced terminology

None.

API changes

Validation is tightened to actual valid props/slots.

Data model changes

JSON Schema changes are more restrictive, but we were restricting on validation anyway.

Release notes snippet

Single-directory component prop and slot names are now restricted to valid Twig identifiers (letters, digits, and underscores; must start with a letter or underscore).

Issue fork drupal-3465228

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

Wim Leers created an issue. See original summary.

quietone’s picture

Version: 11.0.x-dev » 11.x-dev
pdureau’s picture

Hi Wim,

Thanks for this valuable feedback. It makes sense for props (and also slots) machine names to follow machine_name data type: https://www.drupal.org/node/2954832

With:

  constraints:
    Regex: '/^[a-z0-9_]+$/'
    Length:
      max: 64

So:

foo ✅
foo1 ✅
111 ✅
foo_bar ✅
foo-bar ❌
foo bar ❌

We can enforce it to patternProperties in JSON Schema.

cosmicdreams’s picture

I started looking into making this. On the surface this seems to be the responsibility of Drupal/Core/Theme/ComponentPluginManager.php. That would be a place where we could alter the schema validation logic of a Component definitition.

But the configuration shown above seems to be a solution that can be applied to each individual component schema definition. As in, it would be the responsibility of the developer to include the schema constraint per property.

Are you saying it's possible to modify the schema of a component, through the same config-based fix, that would impact the default definition of any property the component might have?

wim leers’s picture

#3++ … except … that

#4: No, @pdureau is proposing to update https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json … which interestingly lives outside Drupal core 😱😅 (Is there an issue to change that? Was that a conscious choice? I cannot find docs covering that. 🤔)

pdureau’s picture

kristen pol’s picture

vensires made their first commit to this issue’s fork.

vensires’s picture

Status: Active » Needs work

@pdureau, I am not so familiar with the *.schema.json syntax etc but we currently have the following:

"props": {
  "$ref": "http://json-schema.org/draft-04/schema#"
},
"slots": {
  "$ref": "#/$defs/slotDefinition"
},

So, where could these constraints be added in the schema.json file?

pdureau’s picture

Hello Panagiotis,

This would be my (non tested) proposal for slots. Remove the - from /"$defs"/slotDefinition/patternProperties/"^[a-zA-Z0-9_-]$". So: /"$defs"/slotDefinition/patternProperties/"^[a-zA-Z0-9_]$"

Unfortunately, I don't think it is possible to enforce it for props because we are delegating the schema to http://json-schema.org/draft-04/schema#

mradcliffe’s picture

I performed Novice Triage on this issue. I added the Novice issue tag and the Needs issue summary update issue tag so that the notes provided by @pdureau can be added to the issue summary to clarify the scope of the issue.

A waving hand indicating a greeting. Novice issue reserved for the Mentored Contribution during the DrupalCon Atlanta 2025 contribution day. After 2025.03.27, this issue returns to being open to all. Thanks
lirak’s picture

Issue summary: View changes

During DrupalCon Atlanta Kwiseman helped me update the proposed resolution.

pdureau credited kwiseman.

pdureau’s picture

@lirak : can you do a MR please?

penyaskito’s picture

Added #3519917: Disable additionalProperties in slots in SDC json schema as related.

The patternProperties regexp means that properties that match that regexp will require those validation rules. But not that properties MUST match that regexp.

gengo_k’s picture

I am removing the Novice tag from this issue because it does not have clear steps at this point.

I’m using this documentation as a source: https://www.drupal.org/community/contributor-guide/task/triage-novice-is...

gengo_k’s picture

Issue tags: -Novice

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

penyaskito’s picture

Assigned: Unassigned » penyaskito

I'm working on this.

penyaskito’s picture

Title: Twig disallows dashes in variable names, so SDC should disallow it in prop names » Twig disallows dashes in variable names, so SDC should disallow it in prop names and slots

Expanded issue title to slots too (still needing IS update).


Variants are not affected, those don't convert to Twig variables. Adding a explicit positive test for that here too.

penyaskito’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests

@pdureau #10: Apparently it's possible!

      "allOf": [
        { "$ref": "http://json-schema.org/draft-04/schema#" },
        {
          "properties": {
            "properties": {
              "additionalProperties": false,
              "patternProperties": {
                "^[a-zA-Z_][a-zA-Z0-9_]*$": {}
              }
            }
          }
        }

Tested this and it worked.

I went a bit further and constrained to: ^[a-zA-Z_][a-zA-Z0-9_]*$, AKA the php valid variable validator, which in absence of more concrete twig docs, it's what twig supports: start with letter or underscore, contain letters, digits, underscores. The only difference is that php allows non-ASCII characters. I think we are fine being more restrictive, because we weren't allowing that before anyway.

Expanded test coverage covering these, both for props and slots.
We were already using additionalProperties: false, so are enforcing all of them.

For variants we don't need this, they don't convert to php/twig variables. Left meta:enum untouched too.

I used $comment for documenting this too. This is hard to maintain, so any help should be welcome. But happy to remove that if you don't agree.

penyaskito’s picture

Issue tags: +AI-accelerated

Disclosure: I used AI (Claude - Opus 4.7) for validating my assumptions with variants and meta:enums not affected, and for comparing our new regex with the one at https://www.php.net/manual/en/language.variables.basics.php and explaining the differences.

penyaskito’s picture

Issue summary: View changes
Issue tags: -Needs issue summary update

Updated IS update.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new1.27 KB

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

pdureau’s picture

@pdureau #10: Apparently it's possible! Tested this and it worked.

Wow! That sounds great. I am a bit surprised with a schema without a type at the root level, my JSON schema knowledge is still expanding.

For variants we don't need this, they don't convert to php/twig variables. Left meta:enum untouched too.

Indeed, they are variable values, not variables names.

penyaskito’s picture

Assigned: penyaskito » Unassigned
Status: Needs work » Needs review
penyaskito’s picture

draft-06 is supported by justinrainbow, and that would have support for propertyNames.

smustgrave’s picture

Seems there's 1 open thread from @penyaskito and 1 comment about a follow up.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Thanks for responding to it. Believe all feedback has been addressed for this one.

  • longwave committed 29fac2e9 on 11.x
    task: #3465228 Twig disallows dashes in variable names, so SDC should...

  • longwave committed ea8be0f9 on 12.0.x
    task: #3465228 Twig disallows dashes in variable names, so SDC should...

  • longwave committed 7dd6a4c9 on main
    task: #3465228 Twig disallows dashes in variable names, so SDC should...
longwave’s picture

Version: main » 11.x-dev
Status: Reviewed & tested by the community » Fixed

Debated whether to add a change record but as far as I can see if you tried to do this before it never would have worked properly anyway.

As this is a minor behaviour change let's just ship it in 11.5 and 12.0 only.

Committed and pushed 7dd6a4c9d48 to main and ea8be0f9dc3 to 12.0.x and 29fac2e9834 to 11.x. Thanks!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

gábor hojtsy’s picture

Canvas has test-slot, test-slot-only-required, new-slot and 0-slot, which is how I came here :) While that indeed would not have worked, this fails Canvas tests on what will become 11.5. Opened https://git.drupalcode.org/project/canvas/-/work_items/3592273 for this.

This may or may not indicate a change record is needed since dashes only worked in a limited way in tests, not in actual rendering, even in Canvas.