Search code examples
cssregexsassstylelint

Regex for camel case BEM


I need a regex pattern to match camel case BEM classes following this structure:

BlockName_elementName-modifierName

I've created this regex to do the job:

([A-Z][a-z0-9]+)+(\_[a-z0-9]+[A-Z0-9]?[a-z0-9]*)?(\-[a-z0-9]+[A-Z0-9]?[a-z0-9]*)?

Examples of strings that should match:

Block
BlockName
BlockNameLonger
BlockName93

BlockName_element
BlockName_elementName
BlockName_elementNameLonger
BlockName_4elementName

BlockName_elementName-modifier
BlockName_elementName-modifierName
BlockName_elementName-modifierNameLonger
BlockName_elementName-modifier567Name

Currently it matches all except the 'longer' strings. I can't work out how to group correctly to match any length of camel case groups. Can anyone help?

See demo here: http://regexr.com/3h0sf


Solution

  • Original: ([A-Z][a-z0-9]+)+(\_[a-z0-9]+[A-Z0-9]?[a-z0-9]*)?(\-[a-z0-9]+[A-Z0-9]?[a-z0-9]*)?

    Split into groups to understand what each is matching:

    • ([A-Z][a-z0-9]+)+ At least 1 group of 1 Uppercase and at least 1 lower/number

    • (\_[a-z0-9]+[A-Z0-9]?[a-z0-9]*)? Optionally, an underscore followed by some number of lower/number, then optionally one upper, then any amount of lower/number

    • (\-[a-z0-9]+[A-Z0-9]?[a-z0-9]*)? Same as above, except starting with a dash.

    We need to change the 2nd and 3rd to behave like the 1st after a group of lowercase, so we just need to splice it into them:

    • (\_[a-z0-9]+([A-Z][a-z0-9]+)*)? (Change the + to a * because there might not be any uppercase groups)

    • (\-[a-z0-9]+([A-Z][a-z0-9]+)*)?

    All together:

    ([A-Z][a-z0-9]+)+(\_[a-z0-9]+([A-Z][a-z0-9]+)*)?(\-[a-z0-9]+([A-Z][a-z0-9]+)*)?