parser.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. var _icssReplaceSymbols = require("icss-replace-symbols");
  6. var _icssReplaceSymbols2 = _interopRequireDefault(_icssReplaceSymbols);
  7. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  8. // Copied from https://github.com/css-modules/css-modules-loader-core
  9. const importRegexp = /^:import\((.+)\)$/;
  10. class Parser {
  11. constructor(pathFetcher, trace) {
  12. this.pathFetcher = pathFetcher;
  13. this.plugin = this.plugin.bind(this);
  14. this.exportTokens = {};
  15. this.translations = {};
  16. this.trace = trace;
  17. }
  18. plugin() {
  19. const parser = this;
  20. return {
  21. postcssPlugin: "css-modules-parser",
  22. OnceExit(css) {
  23. return Promise.all(parser.fetchAllImports(css)).then(() => parser.linkImportedSymbols(css)).then(() => parser.extractExports(css));
  24. }
  25. };
  26. }
  27. fetchAllImports(css) {
  28. let imports = [];
  29. css.each(node => {
  30. if (node.type == "rule" && node.selector.match(importRegexp)) {
  31. imports.push(this.fetchImport(node, css.source.input.from, imports.length));
  32. }
  33. });
  34. return imports;
  35. }
  36. linkImportedSymbols(css) {
  37. (0, _icssReplaceSymbols2.default)(css, this.translations);
  38. }
  39. extractExports(css) {
  40. css.each(node => {
  41. if (node.type == "rule" && node.selector == ":export") this.handleExport(node);
  42. });
  43. }
  44. handleExport(exportNode) {
  45. exportNode.each(decl => {
  46. if (decl.type == "decl") {
  47. Object.keys(this.translations).forEach(translation => {
  48. decl.value = decl.value.replace(translation, this.translations[translation]);
  49. });
  50. this.exportTokens[decl.prop] = decl.value;
  51. }
  52. });
  53. exportNode.remove();
  54. }
  55. fetchImport(importNode, relativeTo, depNr) {
  56. let file = importNode.selector.match(importRegexp)[1],
  57. depTrace = this.trace + String.fromCharCode(depNr);
  58. return this.pathFetcher(file, relativeTo, depTrace).then(exports => {
  59. importNode.each(decl => {
  60. if (decl.type == "decl") {
  61. this.translations[decl.prop] = exports[decl.value];
  62. }
  63. });
  64. importNode.remove();
  65. }, err => console.log(err));
  66. }
  67. }
  68. exports.default = Parser;