format.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. //
  2. // format - printf-like string formatting for JavaScript
  3. // github.com/samsonjs/format
  4. // @_sjs
  5. //
  6. // Copyright 2010 - 2013 Sami Samhuri <sami@samhuri.net>
  7. //
  8. // MIT License
  9. // http://sjs.mit-license.org
  10. //
  11. ;(function() {
  12. //// Export the API
  13. var namespace;
  14. // CommonJS / Node module
  15. if (typeof module !== 'undefined') {
  16. namespace = module.exports = format;
  17. }
  18. // Browsers and other environments
  19. else {
  20. // Get the global object. Works in ES3, ES5, and ES5 strict mode.
  21. namespace = (function(){ return this || (1,eval)('this') }());
  22. }
  23. namespace.format = format;
  24. namespace.vsprintf = vsprintf;
  25. if (typeof console !== 'undefined' && typeof console.log === 'function') {
  26. namespace.printf = printf;
  27. }
  28. function printf(/* ... */) {
  29. console.log(format.apply(null, arguments));
  30. }
  31. function vsprintf(fmt, replacements) {
  32. return format.apply(null, [fmt].concat(replacements));
  33. }
  34. function format(fmt) {
  35. var argIndex = 1 // skip initial format argument
  36. , args = [].slice.call(arguments)
  37. , i = 0
  38. , n = fmt.length
  39. , result = ''
  40. , c
  41. , escaped = false
  42. , arg
  43. , tmp
  44. , leadingZero = false
  45. , precision
  46. , nextArg = function() { return args[argIndex++]; }
  47. , slurpNumber = function() {
  48. var digits = '';
  49. while (/\d/.test(fmt[i])) {
  50. digits += fmt[i++];
  51. c = fmt[i];
  52. }
  53. return digits.length > 0 ? parseInt(digits) : null;
  54. }
  55. ;
  56. for (; i < n; ++i) {
  57. c = fmt[i];
  58. if (escaped) {
  59. escaped = false;
  60. if (c == '.') {
  61. leadingZero = false;
  62. c = fmt[++i];
  63. }
  64. else if (c == '0' && fmt[i + 1] == '.') {
  65. leadingZero = true;
  66. i += 2;
  67. c = fmt[i];
  68. }
  69. else {
  70. leadingZero = true;
  71. }
  72. precision = slurpNumber();
  73. switch (c) {
  74. case 'b': // number in binary
  75. result += parseInt(nextArg(), 10).toString(2);
  76. break;
  77. case 'c': // character
  78. arg = nextArg();
  79. if (typeof arg === 'string' || arg instanceof String)
  80. result += arg;
  81. else
  82. result += String.fromCharCode(parseInt(arg, 10));
  83. break;
  84. case 'd': // number in decimal
  85. result += parseInt(nextArg(), 10);
  86. break;
  87. case 'f': // floating point number
  88. tmp = String(parseFloat(nextArg()).toFixed(precision || 6));
  89. result += leadingZero ? tmp : tmp.replace(/^0/, '');
  90. break;
  91. case 'j': // JSON
  92. result += JSON.stringify(nextArg());
  93. break;
  94. case 'o': // number in octal
  95. result += '0' + parseInt(nextArg(), 10).toString(8);
  96. break;
  97. case 's': // string
  98. result += nextArg();
  99. break;
  100. case 'x': // lowercase hexadecimal
  101. result += '0x' + parseInt(nextArg(), 10).toString(16);
  102. break;
  103. case 'X': // uppercase hexadecimal
  104. result += '0x' + parseInt(nextArg(), 10).toString(16).toUpperCase();
  105. break;
  106. default:
  107. result += c;
  108. break;
  109. }
  110. } else if (c === '%') {
  111. escaped = true;
  112. } else {
  113. result += c;
  114. }
  115. }
  116. return result;
  117. }
  118. }());