rules-fabric.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. var decls = require('./decls.json');
  2. function template(string, data) {
  3. return string.replace(/\$\{([\w\-\.]*)\}/g, function (_str, key) {
  4. var v = data[key];
  5. return typeof v !== 'undefined' && v !== null ? v : '';
  6. });
  7. }
  8. /*
  9. Rules legend:
  10. - combined - if rule is combined it will be rendered with template
  11. - combined and basic rules are present in basic reset
  12. - combined, basic and inherited rules are present in full reset
  13. */
  14. function _getRulesMap(inputDecls) {
  15. return inputDecls
  16. .filter(function (decl) {
  17. return !decl.combined;
  18. })
  19. .reduce(function (map, decl) {
  20. map[decl.prop.replace(/\-/g, '')] = decl.initial;
  21. return map;
  22. }, {});
  23. }
  24. function _compileDecls(inputDecls) {
  25. var templateVars = _getRulesMap(inputDecls);
  26. return inputDecls.map(function (decl) {
  27. if (decl.combined && decl.initial) {
  28. decl.initial = template(decl.initial.replace(/\-/g, ''), templateVars);
  29. }
  30. return decl;
  31. });
  32. }
  33. function _getRequirements(inputDecls) {
  34. return inputDecls.reduce(function (map, decl) {
  35. if (!decl.contains) return map;
  36. return decl.contains.reduce(function (mapInner, dependency) {
  37. mapInner[dependency] = decl;
  38. return mapInner;
  39. }, map);
  40. }, {});
  41. }
  42. function _expandContainments(inputDecls) {
  43. var requiredMap = _getRequirements(inputDecls);
  44. return inputDecls
  45. .filter(function (decl) {
  46. return !decl.contains;
  47. }).map(function (decl) {
  48. var dependency = requiredMap[decl.prop];
  49. if (dependency) {
  50. decl.requiredBy = dependency.prop;
  51. decl.basic = decl.basic || dependency.basic;
  52. decl.inherited = decl.inherited || dependency.inherited;
  53. }
  54. return decl;
  55. });
  56. }
  57. var compiledDecls = _expandContainments(_compileDecls(decls));
  58. function _clearDecls(rules, value) {
  59. return rules.map(function (rule) {
  60. return {
  61. prop: rule.prop,
  62. value: value.replace(/\binitial\b/g, rule.initial)
  63. };
  64. });
  65. }
  66. function _allDecls(onlyInherited) {
  67. return compiledDecls.filter(function (decl) {
  68. var allowed = decl.combined || decl.basic;
  69. if (onlyInherited) return allowed && decl.inherited;
  70. return allowed;
  71. });
  72. }
  73. function _concreteDecl(declName) {
  74. return compiledDecls.filter(function (decl) {
  75. return declName === decl.prop || declName === decl.requiredBy;
  76. });
  77. }
  78. function makeFallbackFunction(onlyInherited) {
  79. return function (declName, declValue) {
  80. var result;
  81. if (declName === 'all') {
  82. result = _allDecls(onlyInherited);
  83. } else {
  84. result = _concreteDecl(declName);
  85. }
  86. return _clearDecls(result, declValue);
  87. };
  88. }
  89. module.exports = makeFallbackFunction;