Skip to content

Instantly share code, notes, and snippets.

@mafraqs
Created May 15, 2015 13:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mafraqs/b1e427d13a18dbef602a to your computer and use it in GitHub Desktop.
Save mafraqs/b1e427d13a18dbef602a to your computer and use it in GitHub Desktop.
Generated by SassMeister.com.
// ----
// libsass (v3.2.4)
// Sass (v3.4.13)
// Compass (v1.0.3)
// ----
///
/// Customization modules
///
/// @type {Map}
///
$customizer: (
"theme-1": (
"primary": (
"lightest": t1pc1,
"light": t1pc2,
"base": t1pc3,
"dark": t1pc4,
"darkest": t1pc5,
),
"complementary": (
"light": t1cc1,
"base": t1cc2,
"dark": t1cc3,
),
"gray": (
"light": t1gc1,
"base": t1gc2,
"dark": t1gc3,
),
"black": t1b,
"white": t1w,
),
"theme-2": (
"primary": (
"lightest": t2pc1,
"light": t2pc2,
"base": t2pc3,
"dark": t2pc4,
"darkest": t2pc5,
),
"complementary": (
"light": t2cc1,
"base": t2cc2,
"dark": t2cc3,
),
"gray": (
"light": t2gc1,
"base": t2gc2,
"dark": t2gc3,
),
"black": t2b,
"white": t2w,
),
) !global;
///
/// Helper functions
///
///
/// Fetch value from map
///
/// @param {Map} $map - map to fetch value from
/// @param {ArgList} $keys - list of keys to traverse
///
/// @return {*}
///
@function map-fetch($map, $keys...) {
$result: $map;
@each $key in $keys {
@if $result {
$result: type-of($result) == "map" and map-has-key($result, $key) and map-get($result, $key) or false;
} @else {
@return false;
}
}
@return $result;
}
///
/// Check if key exists in map
///
/// @param {Map} $map - map to search
/// @param {String} $value - key to search for
///
/// @return {Bool}
///
@function exists($map, $value){
$is-map: type-of($map) == "map";
$top-has-key: $is-map and map-has-key($map, $value) or false;
@if $top-has-key {
@return true;
} @else if $is-map {
@each $m, $k in $map {
@if exists($k, $value) {
@return true;
}
}
}
@return false;
}
///
/// Map of instances
///
/// @type {Map}
///
$customizer-instances: () !global;
///
/// Create new customizable instance
///
/// @param {Map} $arg - map of customizable property->value pairs
/// @param {String} $module - module to pull property values from
///
/// @return {Map} $customizer-instances
///
@function new-customizer-instance($args, $module) {
// Empty argument map
$instance-properties: ();
// Run through each argument individually
@each $arg in $args {
$property: nth($arg, 1);
$value: nth($arg, 2);
// Build temp map to merge into $instance-properties for each property
$temp: (
"#{$property}": (
"module": $module,
"value": $value
)
);
// Merge into argument map
$instance-properties: map-merge($instance-properties, $temp);
}
// Create new instance map for selector, save properties
$customizer-instance: (
"#{&}": (
$instance-properties
)
);
// Check if selector already exists, if so, merge instance vars
@if exists($customizer-instances, "#{&}") {
$self: map-fetch($customizer-instances, "#{&}");
// Merge new vars into self, then merge into main map
@return map-merge($customizer-instances, map-merge($self, $customizer-instance));
}
// Merge into main map
@return map-merge($customizer-instances, $customizer-instance);
}
///
/// Return value for property based on passed module
///
/// @param {List} $args - list of keys for customizable property
/// @param {String} $module - module to pull property values from
///
/// @return {*} - $value from $module
///
@function use-module($args, $module) {
// Module to use
$use: $module;
// Make sure all submodules exist
$exists: true;
// Grab length of arguments
$length: length($args);
// Break down arguments into list to pass into map-fetch
@each $arg in $args {
$use: append($use, $arg);
}
// Check if sub-modules exist
@if $length > 1 {
@for $i from 1 through $length {
@if not exists($customizer, nth($args, $i)) {
$exists: false;
}
}
}
@if $exists {
// Grab value from module by passing in newly built list
@return map-fetch($customizer, $use...);
} @else {
// One or more of the modules were not found, throw error
@warn "Invalid arguments: #{$use}. One or more module or sub-module not found.";
@return $exists;
}
}
///
/// Create new customizable instance
///
/// @param {Map} $args - map of customizable property->value pairs
/// @param {String} $module - module to pull property values from
///
/// @return {Map} $customizer-instances
///
@mixin new-customizer-instance($args, $module) {
$customizer-instances: new-customizer-instance($args, $module) !global;
}
/// Create new customizable properties, save to instance map
///
/// @param {Map} $args - map of customizable property->value pairs
/// @param {String} $module - module to pull property values from
///
/// @output $property->$value pairs for each argument
///
@mixin customizer($args, $uses: null) {
// Make sure argument is a map
@if type-of($args) == "map" {
// Use module? Expecting module to exist
@if $uses != null {
// Check if module exists
@if exists($customizer, $uses) {
// Save arguments to instance map
@include new-customizer-instance($args, $uses);
// Run through each argument individually
@each $arg in $args {
// Break up argument into property->value
$property: nth($arg, 1);
$value: nth($arg, 2);
// Check if sub-module exists
@if type-of($value) == "list" or exists($customizer, $value) {
// Get values from sub-module
$value: use-module($value, $uses);
// Sub-module did not exist, throw error
} @else {
@warn "Invalid argument: #{$value}. Sub-module was not found.";
}
// Output styles
#{$property}: $value;
}
// Module did not exist, throw error
} @else {
@warn "Invalid argument: #{$uses}. Module was not found.";
}
// No module specified, expecting plain CSS
} @else {
// Loop through each argument individually
@each $arg in $args {
// Break up argument into property->value
$property: nth($arg, 1);
$value: nth($arg, 2);
// Output styles
#{$property}: $value;
}
// Warn that customization mixin shouldn't be used without a module
@warn "The customization mixin should not be used without specifying a module to use.";
}
// Argument was not a map, throw error
} @else {
@warn "Invalid argument: #{$args}. Argument type is not a map.";
}
}
///
/// Themify
///
@mixin themify ($customizer: $customizer) {
@each $theme, $map in $customizer {
.#{$theme} & {
// Save the current theme to a global variable so
// that we can use it outside of themify()
$theme: $theme !global;
@content;
// After we're done with it, reset the current active
// theme to null
$theme: null !global;
}
}
}
///
/// Tests
///
/// Normal usage of customizer
// .customizer {
// @include customizer(
// $args: (
// color: "white",
// background: "primary" "darkest",
// border-color: "complementary" "base"
// ),
// $uses: "theme-1"
// );
// }
// Attempt to use themes through "themify"
// but fails because of a missing variable that needs to be passed to $uses
.side-nav {
@include themify() {
@include customizer(
$args: (
color: "primary" "dark"
),
$uses: $theme // This is a global variable
);
}
}
output {
instances: inspect($customizer-instances);
}
.theme-1 .side-nav {
color: t1pc4;
}
.theme-2 .side-nav {
color: t2pc4;
}
output {
instances: (".theme-1 .side-nav": ("color": ("module": "theme-1", "value": "primary" "dark")), ".theme-2 .side-nav": ("color": ("module": "theme-2", "value": "primary" "dark")));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment