UNPKG

3.18 kBJavaScriptView Raw
1/*
2 * MIT License http://opensource.org/licenses/MIT
3 * Author: Ben Holloway @bholloway
4 */
5'use strict';
6
7var os = require('os'),
8 path = require('path'),
9 postcss = require('postcss');
10
11var fileProtocol = require('../file-protocol');
12
13var ORPHAN_CR_REGEX = /\r(?!\n)(.|\n)?/g;
14
15/**
16 * Process the given CSS content into reworked CSS content.
17 *
18 * @param {string} sourceFile The absolute path of the file being processed
19 * @param {string} sourceContent CSS content without source-map
20 * @param {{outputSourceMap: boolean, transformDeclaration:function, absSourceMap:object,
21 * sourceMapConsumer:object, removeCR:boolean}} params Named parameters
22 * @return {{content: string, map: object}} Reworked CSS and optional source-map
23 */
24function process(sourceFile, sourceContent, params) {
25 // #107 libsass emits orphan CR not considered newline, postcss does consider newline (content vs source-map mismatch)
26 var correctedContent = params.removeCR && (os.EOL !== '\r') ?
27 sourceContent.replace(ORPHAN_CR_REGEX, ' $1') :
28 sourceContent;
29
30 // prepend file protocol to all sources to avoid problems with source map
31 return postcss([
32 postcss.plugin('postcss-resolve-url', postcssPlugin)
33 ])
34 .process(correctedContent, {
35 from: fileProtocol.prepend(sourceFile),
36 map : params.outputSourceMap && {
37 prev : !!params.absSourceMap && fileProtocol.prepend(params.absSourceMap),
38 inline : false,
39 annotation : false,
40 sourcesContent: true // #98 sourcesContent missing from output map
41 }
42 })
43 .then(result => ({
44 content: result.css,
45 map : params.outputSourceMap ? fileProtocol.remove(result.map.toJSON()) : null
46 }));
47
48 /**
49 * Plugin for postcss that follows SASS transpilation.
50 */
51 function postcssPlugin() {
52 return function(styles) {
53 styles.walkDecls(eachDeclaration);
54 };
55
56 /**
57 * Process a declaration from the syntax tree.
58 * @param declaration
59 */
60 function eachDeclaration(declaration) {
61 var isValid = declaration.value && (declaration.value.indexOf('url') >= 0);
62 if (isValid) {
63
64 // reverse the original source-map to find the original source file before transpilation
65 var startPosApparent = declaration.source.start,
66 startPosOriginal = params.sourceMapConsumer &&
67 params.sourceMapConsumer.originalPositionFor(startPosApparent);
68
69 // we require a valid directory for the specified file
70 var directory =
71 startPosOriginal &&
72 startPosOriginal.source &&
73 fileProtocol.remove(path.dirname(startPosOriginal.source));
74 if (directory) {
75 declaration.value = params.transformDeclaration(declaration.value, directory);
76 }
77 // source-map present but invalid entry
78 else if (params.sourceMapConsumer) {
79 throw new Error(
80 'source-map information is not available at url() declaration ' +
81 (ORPHAN_CR_REGEX.test(sourceContent) ? '(found orphan CR, try removeCR option)' : '(no orphan CR found)')
82 );
83 }
84 }
85 }
86 }
87}
88
89module.exports = process;