1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4  value: true
5});
6exports.getPostcssConfigHash = getPostcssConfigHash;
7exports.pluginFactory = pluginFactory;
8exports.resolvePostcssConfig = resolvePostcssConfig;
9exports.transformPostCssModule = transformPostCssModule;
10function _jsonFile() {
11  const data = _interopRequireDefault(require("@expo/json-file"));
12  _jsonFile = function () {
13    return data;
14  };
15  return data;
16}
17function _fs() {
18  const data = _interopRequireDefault(require("fs"));
19  _fs = function () {
20    return data;
21  };
22  return data;
23}
24function _path() {
25  const data = _interopRequireDefault(require("path"));
26  _path = function () {
27    return data;
28  };
29  return data;
30}
31function _resolveFrom() {
32  const data = _interopRequireDefault(require("resolve-from"));
33  _resolveFrom = function () {
34    return data;
35  };
36  return data;
37}
38function _require() {
39  const data = require("./utils/require");
40  _require = function () {
41    return data;
42  };
43  return data;
44}
45function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
46function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
47function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
48const CONFIG_FILE_NAME = 'postcss.config';
49const debug = require('debug')('expo:metro:transformer:postcss');
50async function transformPostCssModule(projectRoot, {
51  src,
52  filename
53}) {
54  const inputConfig = resolvePostcssConfig(projectRoot);
55  if (!inputConfig) {
56    return src;
57  }
58  return await processWithPostcssInputConfigAsync(projectRoot, {
59    inputConfig,
60    src,
61    filename
62  });
63}
64async function processWithPostcssInputConfigAsync(projectRoot, {
65  src,
66  filename,
67  inputConfig
68}) {
69  const {
70    plugins,
71    processOptions
72  } = await parsePostcssConfigAsync(projectRoot, {
73    config: inputConfig,
74    resourcePath: filename
75  });
76  debug('options:', processOptions);
77  debug('plugins:', plugins);
78
79  // TODO: Surely this can be cached...
80  const postcss = await Promise.resolve().then(() => _interopRequireWildcard(require('postcss')));
81  const processor = postcss.default(plugins);
82  const {
83    content
84  } = await processor.process(src, processOptions);
85  return content;
86}
87async function parsePostcssConfigAsync(projectRoot, {
88  resourcePath: file,
89  config: {
90    plugins: inputPlugins,
91    map,
92    parser,
93    stringifier,
94    syntax,
95    ...config
96  } = {}
97}) {
98  const factory = pluginFactory();
99  factory(inputPlugins);
100  // delete config.plugins;
101
102  const plugins = [...factory()].map(item => {
103    const [plugin, options] = item;
104    if (typeof plugin === 'string') {
105      return loadPlugin(projectRoot, plugin, options, file);
106    }
107    return plugin;
108  });
109  if (config.from) {
110    config.from = _path().default.resolve(projectRoot, config.from);
111  }
112  if (config.to) {
113    config.to = _path().default.resolve(projectRoot, config.to);
114  }
115  const processOptions = {
116    from: file,
117    to: file,
118    map: false
119  };
120  if (typeof parser === 'string') {
121    try {
122      var _resolveFrom$silent;
123      processOptions.parser = await (0, _require().tryRequireThenImport)((_resolveFrom$silent = _resolveFrom().default.silent(projectRoot, parser)) !== null && _resolveFrom$silent !== void 0 ? _resolveFrom$silent : parser);
124    } catch (error) {
125      if (error instanceof Error) {
126        throw new Error(`Loading PostCSS "${parser}" parser failed: ${error.message}\n\n(@${file})`);
127      }
128      throw error;
129    }
130  }
131  if (typeof stringifier === 'string') {
132    try {
133      var _resolveFrom$silent2;
134      processOptions.stringifier = await (0, _require().tryRequireThenImport)((_resolveFrom$silent2 = _resolveFrom().default.silent(projectRoot, stringifier)) !== null && _resolveFrom$silent2 !== void 0 ? _resolveFrom$silent2 : stringifier);
135    } catch (error) {
136      if (error instanceof Error) {
137        throw new Error(`Loading PostCSS "${stringifier}" stringifier failed: ${error.message}\n\n(@${file})`);
138      }
139      throw error;
140    }
141  }
142  if (typeof syntax === 'string') {
143    try {
144      var _resolveFrom$silent3;
145      processOptions.syntax = await (0, _require().tryRequireThenImport)((_resolveFrom$silent3 = _resolveFrom().default.silent(projectRoot, syntax)) !== null && _resolveFrom$silent3 !== void 0 ? _resolveFrom$silent3 : syntax);
146    } catch (error) {
147      throw new Error(`Loading PostCSS "${syntax}" syntax failed: ${error.message}\n\n(@${file})`);
148    }
149  }
150  if (map === true) {
151    // https://github.com/postcss/postcss/blob/master/docs/source-maps.md
152    processOptions.map = {
153      inline: true
154    };
155  }
156  return {
157    plugins,
158    processOptions
159  };
160}
161function loadPlugin(projectRoot, plugin, options, file) {
162  try {
163    debug('load plugin:', plugin);
164
165    // e.g. `tailwindcss`
166    let loadedPlugin = require((0, _resolveFrom().default)(projectRoot, plugin));
167    if (loadedPlugin.default) {
168      loadedPlugin = loadedPlugin.default;
169    }
170    if (!options || !Object.keys(options).length) {
171      return loadedPlugin;
172    }
173    return loadedPlugin(options);
174  } catch (error) {
175    if (error instanceof Error) {
176      throw new Error(`Loading PostCSS "${plugin}" plugin failed: ${error.message}\n\n(@${file})`);
177    }
178    throw error;
179  }
180}
181function pluginFactory() {
182  const listOfPlugins = new Map();
183  return plugins => {
184    if (typeof plugins === 'undefined') {
185      return listOfPlugins;
186    }
187    if (Array.isArray(plugins)) {
188      for (const plugin of plugins) {
189        if (Array.isArray(plugin)) {
190          const [name, options] = plugin;
191          if (typeof name !== 'string') {
192            throw new Error(`PostCSS plugin must be a string, but "${name}" was found. Please check your configuration.`);
193          }
194          listOfPlugins.set(name, options);
195        } else if (plugin && typeof plugin === 'function') {
196          listOfPlugins.set(plugin, undefined);
197        } else if (plugin && Object.keys(plugin).length === 1 && (typeof plugin[Object.keys(plugin)[0]] === 'object' || typeof plugin[Object.keys(plugin)[0]] === 'boolean') && plugin[Object.keys(plugin)[0]] !== null) {
198          const [name] = Object.keys(plugin);
199          const options = plugin[name];
200          if (options === false) {
201            listOfPlugins.delete(name);
202          } else {
203            listOfPlugins.set(name, options);
204          }
205        } else if (plugin) {
206          listOfPlugins.set(plugin, undefined);
207        }
208      }
209    } else {
210      const objectPlugins = Object.entries(plugins);
211      for (const [name, options] of objectPlugins) {
212        if (options === false) {
213          listOfPlugins.delete(name);
214        } else {
215          listOfPlugins.set(name, options);
216        }
217      }
218    }
219    return listOfPlugins;
220  };
221}
222function resolvePostcssConfig(projectRoot) {
223  // TODO: Maybe support platform-specific postcss config files in the future.
224  const jsConfigPath = _path().default.join(projectRoot, CONFIG_FILE_NAME + '.js');
225  if (_fs().default.existsSync(jsConfigPath)) {
226    debug('load file:', jsConfigPath);
227    return (0, _require().requireUncachedFile)(jsConfigPath);
228  }
229  const jsonConfigPath = _path().default.join(projectRoot, CONFIG_FILE_NAME + '.json');
230  if (_fs().default.existsSync(jsonConfigPath)) {
231    debug('load file:', jsonConfigPath);
232    return _jsonFile().default.read(jsonConfigPath, {
233      json5: true
234    });
235  }
236  return null;
237}
238function getPostcssConfigHash(projectRoot) {
239  // TODO: Maybe recurse plugins and add versions to the hash in the future.
240  const {
241    stableHash
242  } = require('metro-cache');
243  const jsConfigPath = _path().default.join(projectRoot, CONFIG_FILE_NAME + '.js');
244  if (_fs().default.existsSync(jsConfigPath)) {
245    return stableHash(_fs().default.readFileSync(jsConfigPath, 'utf8')).toString('hex');
246  }
247  const jsonConfigPath = _path().default.join(projectRoot, CONFIG_FILE_NAME + '.json');
248  if (_fs().default.existsSync(jsonConfigPath)) {
249    return stableHash(_fs().default.readFileSync(jsonConfigPath, 'utf8')).toString('hex');
250  }
251  return null;
252}
253//# sourceMappingURL=postcss.js.map