10
0

extractICSS.js 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. const importPattern = /^:import\(("[^"]*"|'[^']*'|[^"']+)\)$/;
  2. const balancedQuotes = /^("[^"]*"|'[^']*'|[^"']+)$/;
  3. const getDeclsObject = (rule) => {
  4. const object = {};
  5. rule.walkDecls((decl) => {
  6. const before = decl.raws.before ? decl.raws.before.trim() : "";
  7. object[before + decl.prop] = decl.value;
  8. });
  9. return object;
  10. };
  11. /**
  12. *
  13. * @param {string} css
  14. * @param {boolean} removeRules
  15. * @param {'auto' | 'rule' | 'at-rule'} mode
  16. */
  17. const extractICSS = (css, removeRules = true, mode = "auto") => {
  18. const icssImports = {};
  19. const icssExports = {};
  20. function addImports(node, path) {
  21. const unquoted = path.replace(/'|"/g, "");
  22. icssImports[unquoted] = Object.assign(
  23. icssImports[unquoted] || {},
  24. getDeclsObject(node)
  25. );
  26. if (removeRules) {
  27. node.remove();
  28. }
  29. }
  30. function addExports(node) {
  31. Object.assign(icssExports, getDeclsObject(node));
  32. if (removeRules) {
  33. node.remove();
  34. }
  35. }
  36. css.each((node) => {
  37. if (node.type === "rule" && mode !== "at-rule") {
  38. if (node.selector.slice(0, 7) === ":import") {
  39. const matches = importPattern.exec(node.selector);
  40. if (matches) {
  41. addImports(node, matches[1]);
  42. }
  43. }
  44. if (node.selector === ":export") {
  45. addExports(node);
  46. }
  47. }
  48. if (node.type === "atrule" && mode !== "rule") {
  49. if (node.name === "icss-import") {
  50. const matches = balancedQuotes.exec(node.params);
  51. if (matches) {
  52. addImports(node, matches[1]);
  53. }
  54. }
  55. if (node.name === "icss-export") {
  56. addExports(node);
  57. }
  58. }
  59. });
  60. return { icssImports, icssExports };
  61. };
  62. module.exports = extractICSS;