Skip to content

Instantly share code, notes, and snippets.

@ryanjames
Last active March 10, 2016 06:33
Show Gist options
  • Save ryanjames/8498772759b86aa2bd96 to your computer and use it in GitHub Desktop.
Save ryanjames/8498772759b86aa2bd96 to your computer and use it in GitHub Desktop.
BEV Selector Parsing
// BEVM Selector Processing
// Quick string replace function
@function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
@return $string;
}
// Check if a chunk has any variations
@function hasVariation($chunk) {
$output: str-index($chunk, '--');
@return $output;
}
// Check if a chunk has any elements
@function hasElement($chunk) {
$output: str-index($chunk, '__');
@return $output;
}
@function stripSelectorType($chunk) {
$output: str-replace($chunk,'%','');
$output: str-replace($output,'.','');
@return $output;
}
// If the BEVM isn't assuming any parents, we parse it alone.
@function parseParentlessBEVM($chunk) {
$block: $chunk;
$variation: null;
@if hasVariation($chunk) {
$variationIndex: str-index($chunk, '--');
$variation: str-slice($chunk, $variationIndex, -1);
@if hasElement($variation) {
$variation: null;
}
@else {
$block: str-slice($chunk, 1, $variationIndex - 1);
@if hasVariation($variation) {
$variationIndex: str-index($variation, '--');
$block: #{$block}#{str-slice($variation, 1, $variationIndex - 1)};
$variation: str-slice($variation, $variationIndex, -1);
}
}
}
@return (
type: mixed,
block: $block,
variation: $variation,
modifier: null
);
}
@function parseBEVMSelector($selector) {
// Default BEVM model
$BEVM: (
block: $selector,
variation: null,
modifier: null,
type: basic
);
@if str-index($selector, '-') == 1 and str-index($selector, '--') != 1 {
// If the selector is a -modifier of its parent
$block: stripSelectorType('#{&}');
$BEVM: map-merge($BEVM, (
block: '#{$block} .#{$selector}',
variation: null,
modifier: #{$selector},
type: modifier
));
}
@else if str-index($selector, '--') == 1 {
// If the selector is a --variation requiring its parent as part of the class name
$variation: $selector;
$block: stripSelectorType('#{&}');
// If there's an element declared after the variation delimiter, it's just a variation.
@if hasElement($variation) {
$block: #{$block}#{$selector};
$variation: null;
}
$BEVM: map-merge($BEVM, (
block: $block,
variation: $variation,
modifier: null,
type: variation
));
}
@else {
@if str-index($selector, '__') == 1 {
// If the selector is an __element requiring its parent as part of the class name
$block: stripSelectorType('#{&}');
$BEVM: map-merge($BEVM, (
block: #{$block}#{$selector},
variation: null,
type: element
));
}
// If the selector is not assuming any parents
@else {
$BEVM: parseParentlessBEVM($selector);
}
}
@return $BEVM;
}
@mixin _($selector, $buildClass: null) {
$BEVM: parseBEVMSelector($selector);
$type: map-get($BEVM, type);
$block: map-get($BEVM, block);
$variation: map-get($BEVM, variation);
$modifier: map-get($BEVM, modifier);
@at-root {
// Every new model gets a placeholder.
%#{$block}#{$variation} {
@if $variation {
@extend %#{$block};
};
@content;
}
// If we want to build a class.
@if $buildClass or $modifier {
.#{$block}#{$variation} {
@if $variation {
@extend %#{$block};
};
@content;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment