|
1 | 1 | // tooling |
2 | | -import mergeSourceMaps from './lib/merge-source-maps'; |
3 | | -import postcss from 'postcss'; |
4 | | -import sassResolve from '@csstools/sass-import-resolve'; |
5 | | -import sass from 'sass'; |
6 | | -import { dirname, resolve as pathResolve } from 'path'; |
7 | | - |
8 | | -// transform css with sass |
9 | | -export default postcss.plugin('postcss-sass', opts => (root, result) => { |
10 | | - // postcss configuration |
11 | | - const postConfig = Object.assign({}, result.opts, requiredPostConfig); |
12 | | - |
13 | | - // postcss results |
14 | | - const { css: postCSS, map: postMap } = root.toResult(postConfig); |
15 | | - |
16 | | - // include paths |
17 | | - const includePaths = [].concat(opts && opts.includePaths || []); |
18 | | - |
19 | | - // sass engine to use |
20 | | - const sassEngine = opts && opts.sass || sass |
21 | | - |
22 | | - // sass resolve cache |
23 | | - const cache = {}; |
24 | | - |
25 | | - // replication of the default sass file importer |
26 | | - const defaultSassImporter = (id, parentId, done) => { |
27 | | - // resolve the absolute parent |
28 | | - const parent = pathResolve(parentId); |
29 | | - |
30 | | - // cwds is the list of all directories to search |
31 | | - const cwds = [dirname(parent)].concat(includePaths).map(includePath => pathResolve(includePath)); |
32 | | - |
33 | | - cwds.reduce( |
34 | | - // resolve the first available files |
35 | | - (promise, cwd) => promise.catch( |
36 | | - () => sassResolve(id, { cwd, cache, readFile: true }) |
37 | | - ), |
38 | | - Promise.reject() |
39 | | - ).then( |
40 | | - ({ file, contents }) => { |
41 | | - // pass the file and contents back to sass |
42 | | - done({ file, contents }); |
43 | | - }, |
44 | | - importerError => { |
45 | | - // otherwise, pass the error |
46 | | - done(importerError); |
47 | | - } |
48 | | - ); |
49 | | - } |
50 | | - |
51 | | - // sass importer |
52 | | - const sassImporter = opts && opts.importer || defaultSassImporter |
53 | | - |
54 | | - return new Promise( |
55 | | - // promise sass results |
56 | | - (resolve, reject) => sassEngine.render( |
57 | | - // pass options directly into node-sass |
58 | | - Object.assign({}, opts, requiredSassConfig, { |
59 | | - file: `${postConfig.from}#sass`, |
60 | | - outFile: postConfig.from, |
61 | | - data: postCSS, |
62 | | - importer(id, parentId, done) { |
63 | | - const doneWrap = (importerResult) => { |
64 | | - const file = importerResult && importerResult.file |
65 | | - if (file) { |
66 | | - const parent = pathResolve(parentId); |
67 | | - |
68 | | - // push the dependency to watch tasks |
69 | | - result.messages.push({ type: 'dependency', file, parent }); |
70 | | - } |
71 | | - |
72 | | - done(importerResult) |
73 | | - } |
74 | | - |
75 | | - // strip the #sass suffix we added |
76 | | - const prev = parentId.replace(/#sass$/, '') |
77 | | - |
78 | | - // call the sass importer and catch its output |
79 | | - sassImporter.call(this, id, prev, doneWrap) |
80 | | - } |
81 | | - }), |
82 | | - (sassError, sassResult) => sassError ? reject(sassError) : resolve(sassResult) |
83 | | - ) |
84 | | - ).then( |
85 | | - ({ css: sassCSS, map: sassMap }) => mergeSourceMaps( |
86 | | - postMap.toJSON(), |
87 | | - JSON.parse(sassMap) |
88 | | - ).then(prev => { |
89 | | - // update root to post-node-sass ast |
90 | | - result.root = postcss.parse( |
91 | | - sassCSS.toString(), |
92 | | - Object.assign({}, postConfig, { |
93 | | - map: { prev } |
94 | | - }) |
95 | | - ); |
96 | | - }) |
97 | | - ); |
98 | | -}); |
| 2 | +import mergeSourceMaps from "./lib/merge-source-maps"; |
| 3 | +// import postcss from 'postcss'; |
| 4 | +import sassResolve from "@csstools/sass-import-resolve"; |
| 5 | +import sass from "sass"; |
| 6 | +import { dirname, resolve as pathResolve } from "path"; |
99 | 7 |
|
100 | 8 | const requiredPostConfig = { |
101 | | - map: { |
102 | | - annotation: false, |
103 | | - inline: false, |
104 | | - sourcesContent: true |
105 | | - } |
| 9 | + map: { |
| 10 | + annotation: false, |
| 11 | + inline: false, |
| 12 | + sourcesContent: true, |
| 13 | + }, |
106 | 14 | }; |
107 | 15 |
|
108 | 16 | const requiredSassConfig = { |
109 | | - omitSourceMapUrl: true, |
110 | | - sourceMap: true, |
111 | | - sourceMapContents: true |
| 17 | + omitSourceMapUrl: true, |
| 18 | + sourceMap: true, |
| 19 | + sourceMapContents: true, |
| 20 | +}; |
| 21 | + |
| 22 | +// transform css with sass |
| 23 | +const plugin = (opts = {}) => { |
| 24 | + return { |
| 25 | + postcssPlugin: "postcss-sass", |
| 26 | + Once (root, { result, parse }) { |
| 27 | + // postcss configuration |
| 28 | + const postConfig = Object.assign( |
| 29 | + {}, |
| 30 | + result.opts, |
| 31 | + requiredPostConfig |
| 32 | + ); |
| 33 | + |
| 34 | + // postcss results |
| 35 | + const { css: postCSS, map: postMap } = root.toResult(postConfig); |
| 36 | + |
| 37 | + // include paths |
| 38 | + const includePaths = [].concat(opts && opts.includePaths || []); |
| 39 | + |
| 40 | + // sass engine to use |
| 41 | + const sassEngine = opts && opts.sass || sass; |
| 42 | + |
| 43 | + // sass resolve cache |
| 44 | + const cache = {}; |
| 45 | + |
| 46 | + // replication of the default sass file importer |
| 47 | + const defaultSassImporter = (id, parentId, done) => { |
| 48 | + // resolve the absolute parent |
| 49 | + const parent = pathResolve(parentId); |
| 50 | + |
| 51 | + // cwds is the list of all directories to search |
| 52 | + const cwds = [dirname(parent)] |
| 53 | + .concat(includePaths) |
| 54 | + .map((includePath) => pathResolve(includePath)); |
| 55 | + |
| 56 | + cwds.reduce( |
| 57 | + // resolve the first available files |
| 58 | + (promise, cwd) => |
| 59 | + promise.catch(() => |
| 60 | + sassResolve(id, { |
| 61 | + cwd, |
| 62 | + cache, |
| 63 | + readFile: true, |
| 64 | + }) |
| 65 | + ), |
| 66 | + Promise.reject() |
| 67 | + ).then( |
| 68 | + ({ file, contents }) => { |
| 69 | + // pass the file and contents back to sass |
| 70 | + done({ file, contents }); |
| 71 | + }, |
| 72 | + (importerError) => { |
| 73 | + // otherwise, pass the error |
| 74 | + done(importerError); |
| 75 | + } |
| 76 | + ); |
| 77 | + }; |
| 78 | + |
| 79 | + // sass importer |
| 80 | + const sassImporter = opts && opts.importer || defaultSassImporter; |
| 81 | + |
| 82 | + return new Promise( |
| 83 | + // promise sass results |
| 84 | + (resolve, reject) => |
| 85 | + sassEngine.render( |
| 86 | + // pass options directly into node-sass |
| 87 | + Object.assign({}, opts, requiredSassConfig, { |
| 88 | + file: `${postConfig.from}#sass`, |
| 89 | + outFile: postConfig.from, |
| 90 | + data: postCSS, |
| 91 | + importer(id, parentId, done) { |
| 92 | + const doneWrap = (importerResult) => { |
| 93 | + const file = |
| 94 | + importerResult && importerResult.file; |
| 95 | + if (file) { |
| 96 | + const parent = pathResolve(parentId); |
| 97 | + |
| 98 | + // push the dependency to watch tasks |
| 99 | + result.messages.push({ |
| 100 | + type: "dependency", |
| 101 | + file, |
| 102 | + parent, |
| 103 | + }); |
| 104 | + } |
| 105 | + |
| 106 | + done(importerResult); |
| 107 | + }; |
| 108 | + |
| 109 | + // strip the #sass suffix we added |
| 110 | + const prev = parentId.replace(/#sass$/, ""); |
| 111 | + |
| 112 | + // call the sass importer and catch its output |
| 113 | + sassImporter.call(this, id, prev, doneWrap); |
| 114 | + }, |
| 115 | + }), |
| 116 | + (sassError, sassResult) => |
| 117 | + sassError ? reject(sassError) : resolve(sassResult) |
| 118 | + ) |
| 119 | + ).then(({ css: sassCSS, map: sassMap }) => |
| 120 | + mergeSourceMaps(postMap.toJSON(), JSON.parse(sassMap)).then( |
| 121 | + (prev) => { |
| 122 | + // update root to post-node-sass ast |
| 123 | + result.root = parse( |
| 124 | + sassCSS.toString(), |
| 125 | + Object.assign({}, postConfig, { |
| 126 | + map: { prev }, |
| 127 | + }) |
| 128 | + ); |
| 129 | + } |
| 130 | + ) |
| 131 | + ); |
| 132 | + }, |
| 133 | + }; |
112 | 134 | }; |
| 135 | +plugin.postcss = true; |
| 136 | +export default plugin; |
0 commit comments