source: trip-planner-front/node_modules/postcss-modules-values/src/index.js@ eed0bf8

Last change on this file since eed0bf8 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 4.2 KB
RevLine 
[6a3a178]1"use strict";
2
3const ICSSUtils = require("icss-utils");
4
5const matchImports = /^(.+?|\([\s\S]+?\))\s+from\s+("[^"]*"|'[^']*'|[\w-]+)$/;
6const matchValueDefinition = /(?:\s+|^)([\w-]+):?(.*?)$/;
7const matchImport = /^([\w-]+)(?:\s+as\s+([\w-]+))?/;
8
9module.exports = (options) => {
10 let importIndex = 0;
11 const createImportedName =
12 (options && options.createImportedName) ||
13 ((importName /*, path*/) =>
14 `i__const_${importName.replace(/\W/g, "_")}_${importIndex++}`);
15
16 return {
17 postcssPlugin: "postcss-modules-values",
18 prepare(result) {
19 const importAliases = [];
20 const definitions = {};
21
22 return {
23 Once(root, postcss) {
24 root.walkAtRules(/value/i, (atRule) => {
25 const matches = atRule.params.match(matchImports);
26
27 if (matches) {
28 let [, /*match*/ aliases, path] = matches;
29
30 // We can use constants for path names
31 if (definitions[path]) {
32 path = definitions[path];
33 }
34
35 const imports = aliases
36 .replace(/^\(\s*([\s\S]+)\s*\)$/, "$1")
37 .split(/\s*,\s*/)
38 .map((alias) => {
39 const tokens = matchImport.exec(alias);
40
41 if (tokens) {
42 const [, /*match*/ theirName, myName = theirName] = tokens;
43 const importedName = createImportedName(myName);
44 definitions[myName] = importedName;
45 return { theirName, importedName };
46 } else {
47 throw new Error(`@import statement "${alias}" is invalid!`);
48 }
49 });
50
51 importAliases.push({ path, imports });
52
53 atRule.remove();
54
55 return;
56 }
57
58 if (atRule.params.indexOf("@value") !== -1) {
59 result.warn("Invalid value definition: " + atRule.params);
60 }
61
62 let [, key, value] = `${atRule.params}${atRule.raws.between}`.match(
63 matchValueDefinition
64 );
65
66 const normalizedValue = value.replace(/\/\*((?!\*\/).*?)\*\//g, "");
67
68 if (normalizedValue.length === 0) {
69 result.warn("Invalid value definition: " + atRule.params);
70 atRule.remove();
71
72 return;
73 }
74
75 let isOnlySpace = /^\s+$/.test(normalizedValue);
76
77 if (!isOnlySpace) {
78 value = value.trim();
79 }
80
81 // Add to the definitions, knowing that values can refer to each other
82 definitions[key] = ICSSUtils.replaceValueSymbols(
83 value,
84 definitions
85 );
86
87 atRule.remove();
88 });
89
90 /* If we have no definitions, don't continue */
91 if (!Object.keys(definitions).length) {
92 return;
93 }
94
95 /* Perform replacements */
96 ICSSUtils.replaceSymbols(root, definitions);
97
98 /* We want to export anything defined by now, but don't add it to the CSS yet or it well get picked up by the replacement stuff */
99 const exportDeclarations = Object.keys(definitions).map((key) =>
100 postcss.decl({
101 value: definitions[key],
102 prop: key,
103 raws: { before: "\n " },
104 })
105 );
106
107 /* Add export rules if any */
108 if (exportDeclarations.length > 0) {
109 const exportRule = postcss.rule({
110 selector: ":export",
111 raws: { after: "\n" },
112 });
113
114 exportRule.append(exportDeclarations);
115
116 root.prepend(exportRule);
117 }
118
119 /* Add import rules */
120 importAliases.reverse().forEach(({ path, imports }) => {
121 const importRule = postcss.rule({
122 selector: `:import(${path})`,
123 raws: { after: "\n" },
124 });
125
126 imports.forEach(({ theirName, importedName }) => {
127 importRule.append({
128 value: theirName,
129 prop: importedName,
130 raws: { before: "\n " },
131 });
132 });
133
134 root.prepend(importRule);
135 });
136 },
137 };
138 },
139 };
140};
141
142module.exports.postcss = true;
Note: See TracBrowser for help on using the repository browser.