l0bsterssg

node.js static responsive blog post generator
Log | Files | Refs | README

float.js (2840B)


      1 'use strict';
      2 
      3 var common = require('../common');
      4 var Type   = require('../type');
      5 
      6 var YAML_FLOAT_PATTERN = new RegExp(
      7   // 2.5e4, 2.5 and integers
      8   '^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?' +
      9   // .2e4, .2
     10   // special case, seems not from spec
     11   '|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?' +
     12   // 20:59
     13   '|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*' +
     14   // .inf
     15   '|[-+]?\\.(?:inf|Inf|INF)' +
     16   // .nan
     17   '|\\.(?:nan|NaN|NAN))$');
     18 
     19 function resolveYamlFloat(data) {
     20   if (data === null) return false;
     21 
     22   if (!YAML_FLOAT_PATTERN.test(data) ||
     23       // Quick hack to not allow integers end with `_`
     24       // Probably should update regexp & check speed
     25       data[data.length - 1] === '_') {
     26     return false;
     27   }
     28 
     29   return true;
     30 }
     31 
     32 function constructYamlFloat(data) {
     33   var value, sign, base, digits;
     34 
     35   value  = data.replace(/_/g, '').toLowerCase();
     36   sign   = value[0] === '-' ? -1 : 1;
     37   digits = [];
     38 
     39   if ('+-'.indexOf(value[0]) >= 0) {
     40     value = value.slice(1);
     41   }
     42 
     43   if (value === '.inf') {
     44     return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
     45 
     46   } else if (value === '.nan') {
     47     return NaN;
     48 
     49   } else if (value.indexOf(':') >= 0) {
     50     value.split(':').forEach(function (v) {
     51       digits.unshift(parseFloat(v, 10));
     52     });
     53 
     54     value = 0.0;
     55     base = 1;
     56 
     57     digits.forEach(function (d) {
     58       value += d * base;
     59       base *= 60;
     60     });
     61 
     62     return sign * value;
     63 
     64   }
     65   return sign * parseFloat(value, 10);
     66 }
     67 
     68 
     69 var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;
     70 
     71 function representYamlFloat(object, style) {
     72   var res;
     73 
     74   if (isNaN(object)) {
     75     switch (style) {
     76       case 'lowercase': return '.nan';
     77       case 'uppercase': return '.NAN';
     78       case 'camelcase': return '.NaN';
     79     }
     80   } else if (Number.POSITIVE_INFINITY === object) {
     81     switch (style) {
     82       case 'lowercase': return '.inf';
     83       case 'uppercase': return '.INF';
     84       case 'camelcase': return '.Inf';
     85     }
     86   } else if (Number.NEGATIVE_INFINITY === object) {
     87     switch (style) {
     88       case 'lowercase': return '-.inf';
     89       case 'uppercase': return '-.INF';
     90       case 'camelcase': return '-.Inf';
     91     }
     92   } else if (common.isNegativeZero(object)) {
     93     return '-0.0';
     94   }
     95 
     96   res = object.toString(10);
     97 
     98   // JS stringifier can build scientific format without dots: 5e-100,
     99   // while YAML requres dot: 5.e-100. Fix it with simple hack
    100 
    101   return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res;
    102 }
    103 
    104 function isFloat(object) {
    105   return (Object.prototype.toString.call(object) === '[object Number]') &&
    106          (object % 1 !== 0 || common.isNegativeZero(object));
    107 }
    108 
    109 module.exports = new Type('tag:yaml.org,2002:float', {
    110   kind: 'scalar',
    111   resolve: resolveYamlFloat,
    112   construct: constructYamlFloat,
    113   predicate: isFloat,
    114   represent: representYamlFloat,
    115   defaultStyle: 'lowercase'
    116 });