'use strict'; var features = require('../data/features'); var BrowserSelection = require('./browsers'); var _ = require('lodash'); var formatBrowserName = require('./util').formatBrowserName; var caniuse = require('caniuse-db/fulldata-json/data-1.0'); function filterStats(browsers, stats) { return _.reduce(stats, function (resultStats, versionData, browser) { // filter only versions of selected browsers that don't fully support this feature var feature = _.reduce(versionData, function (result, support, ver) { var selected = browsers.test(browser, ver); if (selected) { // check if browser is NOT fully (i.e., don't have 'y' in their stats) supported if (!/(^|\s)y($|\s)/.test(support)) { // when it's not partially supported ('a'), it's missing var testprop = /(^|\s)a($|\s)/.test(support) ? 'partial' : 'missing'; if (!result[testprop]) { result[testprop] = {}; } result[testprop][selected[1]] = support; } } return result; }, { missing: {}, partial: {} }); if (_.keys(feature.missing).length !== 0) { resultStats.missing[browser] = feature.missing; } if (_.keys(feature.partial).length !== 0) { resultStats.partial[browser] = feature.partial; } return resultStats; }, { missing: {}, partial: {} }); } function lackingBrowsers(browserStats) { return _.reduce(browserStats, function (res, versions, browser) { res.push(formatBrowserName(browser, _.keys(versions))); return res; }, []).join(', '); } /** * Get data on CSS features not supported by the given autoprefixer-like * browser selection. * * @returns `{browsers, features}`, where `features` is an array of: * ``` * { * 'feature-name': { * title: 'Title of feature' * missing: "IE (8), Chrome (31)" * missingData: { * // map of browser -> version -> (lack of)support code * ie: { '8': 'n' }, * chrome: { '31': 'n' } * } * partialData: { * // map of browser -> version -> (partial)support code * ie: { '7': 'a' }, * ff: { '29': 'a #1' } * } * caniuseData: { * // caniuse-db json data for this feature * } * }, * 'feature-name-2': {} // etc. * } * ``` * * `feature-name` is a caniuse-db slug. */ function missing(browserRequest) { var browsers = new BrowserSelection(browserRequest); var result = {}; Object.keys(features).forEach(function (feature) { var featureData = caniuse.data[feature]; var lackData = filterStats(browsers, featureData.stats); var missingData = lackData.missing; var partialData = lackData.partial; // browsers with missing or partial support for this feature var missing = lackingBrowsers(missingData); var partial = lackingBrowsers(partialData); if (missing.length > 0 || partial.length > 0) { result[feature] = { title: featureData.title, caniuseData: featureData }; if (missing.length > 0) { result[feature].missingData = missingData; result[feature].missing = missing; } if (partial.length > 0) { result[feature].partialData = partialData; result[feature].partial = partial; } } }); return { browsers: browsers.list(), features: result }; } module.exports = missing;