| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 | 'use strict';exports.type = 'perItem';exports.active = false;exports.params = {    delim: '__',    prefixIds: true,    prefixClassNames: true,};exports.description = 'prefix IDs';var path = require('path'),    csstree = require('css-tree'),    unquote = require('unquote'),    collections = require('./_collections.js'),    referencesProps = collections.referencesProps,    rxId = /^#(.*)$/, // regular expression for matching an ID + extracing its name    addPrefix = null;// Escapes a string for being used as IDvar escapeIdentifierName = function(str) {    return str.replace(/[\. ]/g, '_');};// Matches an #ID value, captures the ID namevar matchId = function(urlVal) {    var idUrlMatches = urlVal.match(rxId);    if (idUrlMatches === null) {        return false;    }    return idUrlMatches[1];};// Matches an url(...) value, captures the URLvar matchUrl = function(val) {    var urlMatches = /url\((.*?)\)/gi.exec(val);    if (urlMatches === null) {        return false;    }    return urlMatches[1];};// Checks if attribute is emptyvar attrNotEmpty = function(attr) {    return (attr && attr.value && attr.value.length > 0);};// prefixes an #IDvar prefixId = function(val) {    var idName = matchId(val);    if (!idName) {        return false;    }    return '#' + addPrefix(idName);};// attr.value helper methods// prefixes a class attribute valuevar addPrefixToClassAttr = function(attr) {    if (!attrNotEmpty(attr)) {        return;    }    attr.value = attr.value.split(/\s+/).map(addPrefix).join(' ');};// prefixes an ID attribute valuevar addPrefixToIdAttr = function(attr) {    if (!attrNotEmpty(attr)) {        return;    }    attr.value = addPrefix(attr.value);};// prefixes a href attribute valuevar addPrefixToHrefAttr = function(attr) {    if (!attrNotEmpty(attr)) {        return;    }    var idPrefixed = prefixId(attr.value);    if (!idPrefixed) {        return;    }    attr.value = idPrefixed;};// prefixes an URL attribute valuevar addPrefixToUrlAttr = function(attr) {    if (!attrNotEmpty(attr)) {        return;    }    // url(...) in value    var urlVal = matchUrl(attr.value);    if (!urlVal) {        return;    }    var idPrefixed = prefixId(urlVal);    if (!idPrefixed) {        return;    }    attr.value = 'url(' + idPrefixed + ')';};/** * Prefixes identifiers * * @param {Object} node node * @param {Object} opts plugin params * @param {Object} extra plugin extra information * * @author strarsis <strarsis@gmail.com> */exports.fn = function(node, opts, extra) {    // skip subsequent passes when multipass is used    if(extra.multipassCount && extra.multipassCount > 0) {        return node;    }    // prefix, from file name or option    var prefix = 'prefix';    if (opts.prefix) {        if (typeof opts.prefix === 'function') {            prefix = opts.prefix(node, extra);        } else {            prefix = opts.prefix;        }    } else if (opts.prefix === false) {        prefix = false;    } else if (extra && extra.path && extra.path.length > 0) {        var filename = path.basename(extra.path);        prefix = filename;    }    // prefixes a normal value    addPrefix = function(name) {        if(prefix === false){            return escapeIdentifierName(name);        }        return escapeIdentifierName(prefix + opts.delim + name);    };    // <style/> property values    if (node.elem === 'style') {        if (node.isEmpty()) {            // skip empty <style/>s            return node;        }        var cssStr = node.content[0].text || node.content[0].cdata || [];        var cssAst = {};        try {            cssAst = csstree.parse(cssStr, {                parseValue: true,                parseCustomProperty: false            });        } catch (parseError) {            console.warn('Warning: Parse error of styles of <style/> element, skipped. Error details: ' + parseError);            return node;        }        var idPrefixed = '';        csstree.walk(cssAst, function(node) {            // #ID, .class            if (((opts.prefixIds        && node.type === 'IdSelector') ||                 (opts.prefixClassNames && node.type === 'ClassSelector')) &&                 node.name) {                node.name = addPrefix(node.name);                return;            }            // url(...) in value            if (node.type === 'Url' &&                node.value.value && node.value.value.length > 0) {                idPrefixed = prefixId(unquote(node.value.value));                if (!idPrefixed) {                    return;                }                node.value.value = idPrefixed;            }        });        // update <style>s        node.content[0].text = csstree.generate(cssAst);        return node;    }    // element attributes    if (!node.attrs) {        return node;    }    // Nodes    if(opts.prefixIds) {        // ID        addPrefixToIdAttr(node.attrs.id);    }    if(opts.prefixClassNames) {        // Class        addPrefixToClassAttr(node.attrs.class);    }    // References    // href    addPrefixToHrefAttr(node.attrs.href);    // (xlink:)href (deprecated, must be still supported)    addPrefixToHrefAttr(node.attrs['xlink:href']);    // (referenceable) properties    for (var referencesProp of referencesProps) {        addPrefixToUrlAttr(node.attrs[referencesProp]);    }    return node;};
 |