/// Syntax Utilities for Extending Susy /// =================================== /// There are many steps involved /// when translating between the Susy syntax layer, /// and the Su core math. /// That entire process can be condensed with these two functions. /// For anyone that wants to access the full power of Susy, /// and build their own plugins, functions, or mixins – /// this is the primary API for compiling user input, /// and accessing the core math. /// /// This is the same technique we use internally, /// to keep our API layer simple and light-weight. /// Every function accepts two arguments, /// a "shorthand" description of the span or context, /// and an optional settings-map to override global defaults. /// /// - Use `susy-compile()` to parse, merge, and normalize /// all the user settings into a single map. /// - Then use `su-call()` to call one of the core math functions, /// with whatever data is needed for that function. /// /// @group plugin-utils /// @see susy-compile /// @see su-call /// /// @example scss - Susy API `gutter` function /// @function susy-gutter( /// $context: susy-get('columns'), /// $config: () /// ) { /// // compile and normalize all user arguments and global settings /// $context: susy-compile($context, $config, 'context-only'); /// // call `su-gutter` with the appropriate data /// @return su-call('su-gutter', $context); /// } /// /// @example scss - Sample `span` mixin for floated grids /// @mixin span( /// $span, /// $config: () /// ) { /// $context: susy-compile($span, $config); /// width: su-call('su-span', $context); /// /// @if index($span, 'last') { /// float: right; /// } @else { /// float: left; /// margin-right: su-call('su-gutter', $context); /// } /// } // Compile // ------- /// Susy's syntax layer has various moving parts, /// with syntax-parsing for the grid/span shorthand, /// and normalization for each of the resulting values. /// The compile function rolls this all together /// in a single call – /// for quick access from our internal API functions, /// or any additional functions and mixins you add to your project. /// Pass user input and configuration maps to the compiler, /// and it will hand back a map of values ready for Su. /// Combine this with the `su-call` function /// to quickly parse, normalize, and process grid calculations. /// /// @group plugin-utils /// @see su-call /// /// @param {list | map} $shorthand - /// Shorthand expression to define the width of the span, /// optionally containing: /// - a count, length, or column-list span; /// - `at $n`, `first`, or `last` location on asymmetrical grids; /// - `narrow`, `wide`, or `wider` for optionally spreading /// across adjacent gutters; /// - `of $n ` for available grid columns /// and spread of the container /// (span counts like `of 6` are only valid /// in the context of symmetrical grids); /// - and `set-gutters $n` to override global gutter settings /// @param {map} $config [null] - /// Optional map of Susy grid configuration settings /// @param {bool} $context-only [false] - /// Allow the parser to ignore span and span-spread values, /// only parsing context and container-spread /// /// @return {map} - /// Parsed and normalized map of settings, /// based on global and local configuration, /// alongwith shorthad adjustments. /// /// @example scss - /// $user-input: 3 wide of susy-repeat(6, 120px) set-gutters 10px; /// $grid-data: susy-compile($user-input, $susy); /// /// @each $key, $value in $grid-data { /// /* #{$key}: #{$value}, */ /// } @function susy-compile( $short, $config: null, $context-only: false ) { // Get and normalize config $config: if($config, susy-settings($config), susy-settings()); $normal-config: susy-normalize($config); // Parse and normalize shorthand @if (type-of($short) != 'map') and (length($short) > 0) { $short: susy-parse($short, $context-only); } $normal-short: susy-normalize($short, $normal-config); // Merge and return @return map-merge($normal-config, $normal-short); } // Call // ---- /// The Susy parsing and normalization process /// results in a map of configuration settings, /// much like the global `$susy` settings map. /// In order to pass that information along to Su math functions, /// the proper values have to be picked out, /// and converted to arguments. /// /// The `su-call` function streamlines that process, /// weeding out the unnecessary data, /// and passing the rest along to Su in the proper format. /// Combine this with `susy-compile` to quickly parse, /// normalize, and process grid calculations. /// /// @group plugin-utils /// /// @require su-span /// @require su-gutter /// @require su-slice /// @see susy-compile /// /// @param {'su-span' | 'su-gutter' | 'su-slice'} $name - /// Name of the Su math function to call. /// @param {map} $config - /// Parsed and normalized map of Susy configuration settings /// to use for math-function arguments. /// /// @return {*} - /// Results of the function being called. /// /// @example scss - /// $user-input: 3 wide of susy-repeat(6, 120px) set-gutters 10px; /// $grid-data: susy-compile($user-input, $susy); /// /// .su-span { /// width: su-call('su-span', $grid-data); /// } @function su-call( $name, $config ) { $grid-function-args: ( 'su-span': ('span', 'columns', 'gutters', 'spread', 'container-spread', 'location'), 'su-gutter': ('columns', 'gutters', 'container-spread'), 'su-slice': ('span', 'columns', 'location'), ); $args: map-get($grid-function-args, $name); @if not $args { $options: 'Try one of these: #{map-keys($grid-function-args)}'; @return _susy-error( '#{$name} is not a public Su function. #{$options}', 'su-call'); } $call: if(function-exists('get-function'), get-function($name), $name); $output: (); @each $arg in $args { $value: map-get($config, $arg); $output: if($value, map-merge($output, ($arg: $value)), $output); } @return call($call, $output...); }