mostly filebased Content Presentation System

164 lines
4.4KB

  1. /// Shorthand Syntax Parser
  2. /// =======================
  3. /// The syntax parser converts [shorthand syntax][short]
  4. /// into a map of settings that can be compared/merged with
  5. /// other config maps and global setting.
  6. ///
  7. /// [short]: api.html
  8. ///
  9. /// @group _parser
  10. // Parse
  11. // -----
  12. /// The `parse` function provides all the syntax-sugar in Susy,
  13. /// converting user shorthand
  14. /// into a usable map of keys and values
  15. /// that can be normalized and passed to Su.
  16. ///
  17. /// @group _parser
  18. /// @see $susy
  19. ///
  20. /// @param {list} $shorthand -
  21. /// Shorthand expression to define the width of the span,
  22. /// optionally containing:
  23. /// - a count, length, or column-list span;
  24. /// - `at $n`, `first`, or `last` location on asymmetrical grids;
  25. /// - `narrow`, `wide`, or `wider` for optionally spreading
  26. /// across adjacent gutters;
  27. /// - `of $n <spread>` for available grid columns
  28. /// and spread of the container
  29. /// (span counts like `of 6` are only valid
  30. /// in the context of symmetrical grids);
  31. /// - and `set-gutters $n` to override global gutter settings
  32. /// @param {bool} $context-only [false] -
  33. /// Allow the parser to ignore span and span-spread values,
  34. /// only parsing context and container-spread.
  35. /// This makes it possible to accept spanless values,
  36. /// like the `gutters()` syntax.
  37. /// When parsing context-only,
  38. /// the `of` indicator is optional.
  39. ///
  40. /// @return {map} -
  41. /// Map of span and grid settings
  42. /// parsed from shorthand input –
  43. /// including all the properties available globally –
  44. /// `columns`, `gutters`, `spread`, `container-spread` –
  45. /// along with the span-specific properties
  46. /// `span`, and `location`.
  47. ///
  48. /// @throw
  49. /// when a shorthand value is not recognized
  50. @function susy-parse(
  51. $shorthand,
  52. $context-only: false
  53. ) {
  54. $parse-error: 'Unknown shorthand property:';
  55. $options: (
  56. 'first': 'location',
  57. 'last': 'location',
  58. 'alpha': 'location',
  59. 'omega': 'location',
  60. 'narrow': 'spread',
  61. 'wide': 'spread',
  62. 'wider': 'spread',
  63. );
  64. $return: ();
  65. $span: null;
  66. $columns: null;
  67. $of: null;
  68. $next: false;
  69. // Allow context-only shorthand, without span
  70. @if ($context-only) and (not index($shorthand, 'of')) {
  71. @if su-valid-columns($shorthand, 'fail-silent') {
  72. $shorthand: 'of' $shorthand;
  73. } @else {
  74. $shorthand: join('of', $shorthand);
  75. }
  76. }
  77. // loop through the shorthand list
  78. @for $i from 1 through length($shorthand) {
  79. $item: nth($shorthand, $i);
  80. $type: type-of($item);
  81. $error: false;
  82. $details: '[#{$type}] `#{$item}`';
  83. // if we know what's supposed to be coming next…
  84. @if $next {
  85. // Add to the return map
  86. $return: map-merge($return, ($next: $item));
  87. // Reset next to `false`
  88. $next: false;
  89. } @else { // If we don't know what's supposed to be coming…
  90. // Keywords…
  91. @if ($type == 'string') {
  92. // Check the map for keywords…
  93. @if map-has-key($options, $item) {
  94. $setting: map-get($options, $item);
  95. // Spread could be on the span or the container…
  96. @if ($setting == 'spread') and ($of) {
  97. $return: map-merge($return, ('container-spread': $item));
  98. } @else {
  99. $return: map-merge($return, ($setting: $item));
  100. }
  101. } @else if ($item == 'all') {
  102. // `All` is a span shortcut
  103. $span: 'all';
  104. } @else if ($item == 'at') {
  105. // Some keywords setup what's next…
  106. $next: 'location';
  107. } @else if ($item == 'set-gutters') {
  108. $next: 'gutters';
  109. } @else if ($item == 'of') {
  110. $of: true;
  111. } @else {
  112. $error: true;
  113. }
  114. } @else if ($type == 'number') or ($type == 'list') { // Numbers & lists…
  115. @if not ($span or $of) {
  116. // We don't have a span, and we're not expecting context…
  117. $span: $item;
  118. } @else if ($of) and (not $columns) {
  119. // We are expecting context…
  120. $columns: $item;
  121. } @else {
  122. $error: true;
  123. }
  124. } @else {
  125. $error: true;
  126. }
  127. }
  128. @if $error {
  129. @return _susy-error('#{$parse-error} #{$details}', 'susy-parse');
  130. }
  131. }
  132. // If we have span, merge it in
  133. @if $span {
  134. $return: map-merge($return, ('span': $span));
  135. }
  136. // If we have columns, merge them in
  137. @if $columns {
  138. $return: map-merge($return, ('columns': $columns));
  139. }
  140. // Return the map of settings…
  141. @return $return;
  142. }