check-css-variables-exist.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. module.exports = plugin;
  2. const utils = require('./utils');
  3. const fs = require('fs');
  4. const regexAssign = /--[a-z-]*:/g;
  5. const regexUsage = /var\(--[a-z-]*\)/g;
  6. const LOG_EVERYTHING = false;
  7. const DEFAULT_ASSIGNMENTS = [
  8. '--black',
  9. '--black-70',
  10. '--black-bis',
  11. '--black-ter',
  12. '--grey-darker',
  13. '--grey-dark',
  14. '--grey',
  15. '--grey-light',
  16. '--grey-lighter',
  17. '--grey-lightest',
  18. '--white-ter',
  19. '--white-bis',
  20. '--white',
  21. '--orange',
  22. '--yellow',
  23. '--green',
  24. '--turquoise',
  25. '--cyan',
  26. '--blue',
  27. '--purple',
  28. '--red',
  29. '--family-sans-serif',
  30. '--family-monospace',
  31. '--render-mode',
  32. '--size-1',
  33. '--size-2',
  34. '--size-3',
  35. '--size-4',
  36. '--size-5',
  37. '--size-6',
  38. '--size-7',
  39. '--weight-light',
  40. '--weight-normal',
  41. '--weight-medium',
  42. '--weight-semibold',
  43. '--weight-bold',
  44. '--block-spacing',
  45. '--easing',
  46. '--radius-small',
  47. '--radius',
  48. '--radius-large',
  49. '--radius-rounded',
  50. '--speed',
  51. '--primary',
  52. '--info',
  53. '--success',
  54. '--warning',
  55. '--danger',
  56. '--light',
  57. '--dark',
  58. '--orange-invert',
  59. '--yellow-invert',
  60. '--green-invert',
  61. '--turquoise-invert',
  62. '--cyan-invert',
  63. '--blue-invert',
  64. '--purple-invert',
  65. '--red-invert',
  66. '--primary-invert',
  67. '--primary-light',
  68. '--primary-dark',
  69. '--info-invert',
  70. '--info-light',
  71. '--info-dark',
  72. '--success-invert',
  73. '--success-light',
  74. '--success-dark',
  75. '--warning-invert',
  76. '--warning-light',
  77. '--warning-dark',
  78. '--danger-invert',
  79. '--danger-light',
  80. '--danger-dark',
  81. '--light-invert',
  82. '--light-light',
  83. '--light-dark',
  84. '--dark-invert',
  85. '--dark-light',
  86. '--dark-dark',
  87. '--scheme-main',
  88. '--scheme-main-bis',
  89. '--scheme-main-ter',
  90. '--scheme-invert',
  91. '--scheme-invert-rgb',
  92. '--scheme-invert-bis',
  93. '--scheme-invert-ter',
  94. '--background',
  95. '--border',
  96. '--border-rgb',
  97. '--border-hover',
  98. '--border-light',
  99. '--border-light-hover',
  100. '--text',
  101. '--text-invert',
  102. '--text-light',
  103. '--text-strong',
  104. '--code',
  105. '--code-background',
  106. '--pre',
  107. '--pre-background',
  108. '--link',
  109. '--link-invert',
  110. '--link-light',
  111. '--link-dark',
  112. '--link-visited',
  113. '--link-hover',
  114. '--link-hover-border',
  115. '--link-focus',
  116. '--link-focus-border',
  117. '--link-active',
  118. '--link-active-border',
  119. '--family-primary',
  120. '--family-secondary',
  121. '--family-code',
  122. '--size-small',
  123. '--size-normal',
  124. '--size-medium',
  125. '--size-large',
  126. '--control-radius',
  127. '--control-radius-small',
  128. '--control-border-width',
  129. '--control-height',
  130. '--control-line-height',
  131. '--control-padding-vertical',
  132. '--control-padding-horizontal',
  133. ];
  134. function logThis(message) {
  135. if (LOG_EVERYTHING) {
  136. console.log(message);
  137. }
  138. }
  139. function plugin() {
  140. return (files, metalsmith, done) => {
  141. setImmediate(done);
  142. let hasErrors = false;
  143. Object.keys(files).forEach(filePath => {
  144. const {fileName, lines} = utils.getLines(files, filePath);
  145. const file = files[filePath];
  146. const contents = file.contents.toString();
  147. const assignments = contents.match(regexAssign);
  148. let errorCount = 0;
  149. if (!assignments) {
  150. logThis(`${filePath} has no CSS var assignments`);
  151. errorCount++;
  152. return;
  153. }
  154. const fileAssignments = assignments.map(assignment => assignment.replace(':', ''));
  155. const allAssignments = [...fileAssignments, ...DEFAULT_ASSIGNMENTS];
  156. let usages = contents.match(regexUsage);
  157. if (!usages) {
  158. logThis(`${filePath} has no CSS var usages`);
  159. errorCount++;
  160. return;
  161. }
  162. // var(--foobar) ==> --foobar
  163. usages = usages.map(usage => {
  164. usage = usage.replace('var(', '');
  165. usage = usage.replace(')', '');
  166. return usage;
  167. });
  168. if (filePath.endsWith('shared.sass')) {
  169. console.log('ZLOG usages', usages);
  170. console.log('ZLOG assignments', fileAssignments);
  171. }
  172. usages.forEach(usage => {
  173. if (!allAssignments.includes(usage)) {
  174. console.log(`${usage} is not assigned`);
  175. errorCount++;
  176. }
  177. });
  178. fileAssignments.forEach(assignment => {
  179. if (!usages.includes(assignment)) {
  180. console.log(`${assignment} is not used`);
  181. errorCount++;
  182. }
  183. });
  184. if (errorCount) {
  185. console.log(`There are some errors in ${filePath}`);
  186. hasErrors = true;
  187. } else {
  188. logThis(`${filePath} is all good!`);
  189. }
  190. });
  191. if (hasErrors) {
  192. console.log(`There are some errors`);
  193. } else {
  194. console.log(`All CSS variables are used and assigned correctly!`);
  195. }
  196. };
  197. }