json.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. var utils = require('../utils')
  2. , nodes = require('../nodes')
  3. , readFile = require('fs').readFileSync;
  4. /**
  5. * Convert a .json file into stylus variables or object.
  6. * Nested variable object keys are joined with a dash (-)
  7. *
  8. * Given this sample media-queries.json file:
  9. * {
  10. * "small": "screen and (max-width:400px)",
  11. * "tablet": {
  12. * "landscape": "screen and (min-width:600px) and (orientation:landscape)",
  13. * "portrait": "screen and (min-width:600px) and (orientation:portrait)"
  14. * }
  15. * }
  16. *
  17. * Examples:
  18. *
  19. * json('media-queries.json')
  20. *
  21. * @media small
  22. * // => @media screen and (max-width:400px)
  23. *
  24. * @media tablet-landscape
  25. * // => @media screen and (min-width:600px) and (orientation:landscape)
  26. *
  27. * vars = json('vars.json', { hash: true })
  28. * body
  29. * width: vars.width
  30. *
  31. * @param {String} path
  32. * @param {Boolean} [local]
  33. * @param {String} [namePrefix]
  34. * @api public
  35. */
  36. function json(path, local, namePrefix){
  37. utils.assertString(path, 'path');
  38. // lookup
  39. path = path.string;
  40. var found = utils.lookup(path, this.options.paths, this.options.filename)
  41. , options = (local && 'object' == local.nodeName) && local;
  42. if (!found) {
  43. // optional JSON file
  44. if (options && options.get('optional').toBoolean().isTrue) {
  45. return nodes.null;
  46. }
  47. throw new Error('failed to locate .json file ' + path);
  48. }
  49. // read
  50. var json = JSON.parse(readFile(found, 'utf8'));
  51. if (options) {
  52. return convert(json, options);
  53. } else {
  54. oldJson.call(this, json, local, namePrefix);
  55. }
  56. function convert(obj, options){
  57. var ret = new nodes.Object()
  58. , leaveStrings = options.get('leave-strings').toBoolean();
  59. for (var key in obj) {
  60. var val = obj[key];
  61. if ('object' == typeof val) {
  62. ret.set(key, convert(val, options));
  63. } else {
  64. val = utils.coerce(val);
  65. if ('string' == val.nodeName && leaveStrings.isFalse) {
  66. val = utils.parseString(val.string);
  67. }
  68. ret.set(key, val);
  69. }
  70. }
  71. return ret;
  72. }
  73. };
  74. json.params = ['path', 'local', 'namePrefix'];
  75. module.exports = json;
  76. /**
  77. * Old `json` BIF.
  78. *
  79. * @api private
  80. */
  81. function oldJson(json, local, namePrefix){
  82. if (namePrefix) {
  83. utils.assertString(namePrefix, 'namePrefix');
  84. namePrefix = namePrefix.val;
  85. } else {
  86. namePrefix = '';
  87. }
  88. local = local ? local.toBoolean() : new nodes.Boolean(local);
  89. var scope = local.isTrue ? this.currentScope : this.global.scope;
  90. convert(json);
  91. return;
  92. function convert(obj, prefix){
  93. prefix = prefix ? prefix + '-' : '';
  94. for (var key in obj){
  95. var val = obj[key];
  96. var name = prefix + key;
  97. if ('object' == typeof val) {
  98. convert(val, name);
  99. } else {
  100. val = utils.coerce(val);
  101. if ('string' == val.nodeName) val = utils.parseString(val.string);
  102. scope.add({ name: namePrefix + name, val: val });
  103. }
  104. }
  105. }
  106. };