<commit_before>var child_process = require('child_process'),
    URL = require('url'),
    path = require('path'),
    glob = require('glob'),
    fs = require('fs'),
    request = require('request'),
    _ = require('underscore'),
    step = require('step'),
    fileUtils = require('./fileUtils'),
    error = require('./error'),
    assets = require('./assets');

function AssetConfigResolver(config) {
    _.extend(this, config || {});
    if (!/^[^:]+:/.test(this.root)) { // No protocol?
        this.root = fileUtils.fsDirToFileUrl(this.root || process.cwd());
    }
    this.protocols = this.protocols || {};
};

AssetConfigResolver.prototype.resolve = function (assetConfig, fromUrl, cb) {
    var that = this;
    if (_.isArray(assetConfig)) {
        // Call ourselves recursively for each item, flatten the results and report back
        if (!assetConfig.length) {
            return process.nextTick(function () {
                cb(null, []);
            });
        } else {
            return step(
                function () {
                    var group = this.group();
                    assetConfig.forEach(function (_assetConfig) {
                        that.resolve(_assetConfig, fromUrl, group());
                    });
                },
                error.passToFunction(cb, function (resolvedAssetConfigs) {
                    cb(null, _.flatten(resolvedAssetConfigs));
                })
            );
        }
    }
    if (typeof assetConfig === 'string') {
        // Move file: wildcard expansion up here?
        if (/^\//.test(assetConfig) && /^file:/.test(that.root)) {
            assetConfig = {url: that.root + assetConfig.substr(1)};
        } else {
            assetConfig = {url: URL.resolve(fromUrl, assetConfig)};
        }
    }
    if (assetConfig.url) {
        var protocol = assetConfig.url.substr(0, assetConfig.url.indexOf(':')),
            pathname = assetConfig.url.replace(/^\w+:(?:\/\/)?/, ""); // Strip protocol and two leading slashes if present
        if (protocol === 'file') {
            if (/[\*\?]/.test(pathname)) {
                // Expand wildcard, then expand each resulting url
                return glob.glob(pathname, error.passToFunction(cb, function (fsPaths) {
                    if (!fsPaths.length) {
                        cb(new Error("AssetGraph.resolveAssetConfig: Wildcard " + pathname + " expanded to nothing"));
                    } else {
                        that.resolve(fsPaths.map(function (fsPath) {
                            return 'file://' + fsPath;
                        }), fromUrl, cb);
                    }
                }));
            }
            assetConfig.originalSrcProxy = function (cb) {
                // Will be invoked in the asset's scope, so this.encoding works out.
                fs.readFile(pathname, this.encoding, cb);
            };
        } else if (protocol === 'http' || protocol === 'https') {
            assetConfig.originalSrcProxy = function (cb) {
                request({
                    url: assetConfig.url,
                    onResponse: true
                }, error.passToFunction(cb, function (response) {<commit_msg>AssetConfigResolver: Fixed resolution of root-relative urls when from non-file:// urls.<commit_after>var child_process = require('child_process'),
    URL = require('url'),
    path = require('path'),
    glob = require('glob'),
    fs = require('fs'),
    request = require('request'),
    _ = require('underscore'),
    step = require('step'),
    fileUtils = require('./fileUtils'),
    error = require('./error'),
    assets = require('./assets');

function AssetConfigResolver(config) {
    _.extend(this, config || {});
    if (!/^[^:]+:/.test(this.root)) { // No protocol?
        this.root = fileUtils.fsDirToFileUrl(this.root || process.cwd());
    }
    this.protocols = this.protocols || {};
};

AssetConfigResolver.prototype.resolve = function (assetConfig, fromUrl, cb) {
    var that = this;
    if (_.isArray(assetConfig)) {
        // Call ourselves recursively for each item, flatten the results and report back
        if (!assetConfig.length) {
            return process.nextTick(function () {
                cb(null, []);
            });
        } else {
            return step(
                function () {
                    var group = this.group();
                    assetConfig.forEach(function (_assetConfig) {
                        that.resolve(_assetConfig, fromUrl, group());
                    });
                },
                error.passToFunction(cb, function (resolvedAssetConfigs) {
                    cb(null, _.flatten(resolvedAssetConfigs));
                })
            );
        }
    }
    if (typeof assetConfig === 'string') {
        if (/^\//.test(assetConfig) && /^file:/.test(fromUrl) && /^file:/.test(that.root)) {
            assetConfig = {url: that.root + assetConfig.substr(1)};
        } else {
            assetConfig = {url: URL.resolve(fromUrl, assetConfig)};
        }
    }
    if (assetConfig.url) {
        var protocol = assetConfig.url.substr(0, assetConfig.url.indexOf(':')),
            pathname = assetConfig.url.replace(/^\w+:(?:\/\/)?/, ""); // Strip protocol and two leading slashes if present
        if (protocol === 'file') {
            if (/[\*\?]/.test(pathname)) {
                // Expand wildcard, then expand each resulting url
                return glob.glob(pathname, error.passToFunction(cb, function (fsPaths) {
                    if (!fsPaths.length) {
                        cb(new Error("AssetGraph.resolveAssetConfig: Wildcard " + pathname + " expanded to nothing"));
                    } else {
                        that.resolve(fsPaths.map(function (fsPath) {
                            return 'file://' + fsPath;
                        }), fromUrl, cb);
                    }
                }));
            }
            assetConfig.originalSrcProxy = function (cb) {
                // Will be invoked in the asset's scope, so this.encoding works out.
                fs.readFile(pathname, this.encoding, cb);
            };
        } else if (protocol === 'http' || protocol === 'https') {
            assetConfig.originalSrcProxy = function (cb) {
                request({
                    url: assetConfig.url,
                    onResponse: true
                }, error.passToFunction(cb, function (response) {
{'fraction_non_alphanumeric': 0.1421461897356143, 'fraction_numerical': 0.0006220839813374805, 'mean_word_length': 1.7146475306036302, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1750583', 'n_tokens_mistral': 1708, 'n_tokens_neox': 1650, 'n_words': 374}