index.cjs.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. 'use strict';
  2. function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
  3. var parser = _interopDefault(require('postcss-selector-parser'));
  4. var fs = _interopDefault(require('fs'));
  5. var path = _interopDefault(require('path'));
  6. var postcss = _interopDefault(require('postcss'));
  7. function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
  8. try {
  9. var info = gen[key](arg);
  10. var value = info.value;
  11. } catch (error) {
  12. reject(error);
  13. return;
  14. }
  15. if (info.done) {
  16. resolve(value);
  17. } else {
  18. Promise.resolve(value).then(_next, _throw);
  19. }
  20. }
  21. function _asyncToGenerator(fn) {
  22. return function () {
  23. var self = this,
  24. args = arguments;
  25. return new Promise(function (resolve, reject) {
  26. var gen = fn.apply(self, args);
  27. function _next(value) {
  28. asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
  29. }
  30. function _throw(err) {
  31. asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
  32. }
  33. _next(undefined);
  34. });
  35. };
  36. }
  37. function _defineProperty(obj, key, value) {
  38. if (key in obj) {
  39. Object.defineProperty(obj, key, {
  40. value: value,
  41. enumerable: true,
  42. configurable: true,
  43. writable: true
  44. });
  45. } else {
  46. obj[key] = value;
  47. }
  48. return obj;
  49. }
  50. function _objectSpread(target) {
  51. for (var i = 1; i < arguments.length; i++) {
  52. var source = arguments[i] != null ? arguments[i] : {};
  53. var ownKeys = Object.keys(source);
  54. if (typeof Object.getOwnPropertySymbols === 'function') {
  55. ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
  56. return Object.getOwnPropertyDescriptor(source, sym).enumerable;
  57. }));
  58. }
  59. ownKeys.forEach(function (key) {
  60. _defineProperty(target, key, source[key]);
  61. });
  62. }
  63. return target;
  64. }
  65. function _slicedToArray(arr, i) {
  66. return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
  67. }
  68. function _arrayWithHoles(arr) {
  69. if (Array.isArray(arr)) return arr;
  70. }
  71. function _iterableToArrayLimit(arr, i) {
  72. var _arr = [];
  73. var _n = true;
  74. var _d = false;
  75. var _e = undefined;
  76. try {
  77. for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
  78. _arr.push(_s.value);
  79. if (i && _arr.length === i) break;
  80. }
  81. } catch (err) {
  82. _d = true;
  83. _e = err;
  84. } finally {
  85. try {
  86. if (!_n && _i["return"] != null) _i["return"]();
  87. } finally {
  88. if (_d) throw _e;
  89. }
  90. }
  91. return _arr;
  92. }
  93. function _nonIterableRest() {
  94. throw new TypeError("Invalid attempt to destructure non-iterable instance");
  95. }
  96. /* Return a Selectors AST from a Selectors String
  97. /* ========================================================================== */
  98. var getSelectorsAstFromSelectorsString = (selectorString => {
  99. let selectorAST;
  100. parser(selectors => {
  101. selectorAST = selectors;
  102. }).processSync(selectorString);
  103. return selectorAST;
  104. });
  105. var getCustomSelectors = ((root, opts) => {
  106. // initialize custom selectors
  107. const customSelectors = {}; // for each custom selector atrule that is a child of the css root
  108. root.nodes.slice().forEach(node => {
  109. if (isCustomSelector(node)) {
  110. // extract the name and selectors from the params of the custom selector
  111. const _node$params$match = node.params.match(customSelectorParamsRegExp),
  112. _node$params$match2 = _slicedToArray(_node$params$match, 3),
  113. name = _node$params$match2[1],
  114. selectors = _node$params$match2[2]; // write the parsed selectors to the custom selector
  115. customSelectors[name] = getSelectorsAstFromSelectorsString(selectors); // conditionally remove the custom selector atrule
  116. if (!Object(opts).preserve) {
  117. node.remove();
  118. }
  119. }
  120. });
  121. return customSelectors;
  122. }); // match the custom selector name
  123. const customSelectorNameRegExp = /^custom-selector$/i; // match the custom selector params
  124. const customSelectorParamsRegExp = /^(:--[A-z][\w-]*)\s+([\W\w]+)\s*$/; // whether the atrule is a custom selector
  125. const isCustomSelector = node => node.type === 'atrule' && customSelectorNameRegExp.test(node.name) && customSelectorParamsRegExp.test(node.params);
  126. // return transformed selectors, replacing custom pseudo selectors with custom selectors
  127. function transformSelectorList(selectorList, customSelectors) {
  128. let index = selectorList.nodes.length - 1;
  129. while (index >= 0) {
  130. const transformedSelectors = transformSelector(selectorList.nodes[index], customSelectors);
  131. if (transformedSelectors.length) {
  132. selectorList.nodes.splice(index, 1, ...transformedSelectors);
  133. }
  134. --index;
  135. }
  136. return selectorList;
  137. } // return custom pseudo selectors replaced with custom selectors
  138. function transformSelector(selector, customSelectors) {
  139. const transpiledSelectors = [];
  140. for (const index in selector.nodes) {
  141. const _selector$nodes$index = selector.nodes[index],
  142. value = _selector$nodes$index.value,
  143. nodes = _selector$nodes$index.nodes;
  144. if (value in customSelectors) {
  145. var _iteratorNormalCompletion = true;
  146. var _didIteratorError = false;
  147. var _iteratorError = undefined;
  148. try {
  149. for (var _iterator = customSelectors[value].nodes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
  150. const replacementSelector = _step.value;
  151. const selectorClone = selector.clone();
  152. selectorClone.nodes.splice(index, 1, ...replacementSelector.clone().nodes.map(node => {
  153. // use spacing from the current usage
  154. node.spaces = _objectSpread({}, selector.nodes[index].spaces);
  155. return node;
  156. }));
  157. const retranspiledSelectors = transformSelector(selectorClone, customSelectors);
  158. adjustNodesBySelectorEnds(selectorClone.nodes, Number(index));
  159. if (retranspiledSelectors.length) {
  160. transpiledSelectors.push(...retranspiledSelectors);
  161. } else {
  162. transpiledSelectors.push(selectorClone);
  163. }
  164. }
  165. } catch (err) {
  166. _didIteratorError = true;
  167. _iteratorError = err;
  168. } finally {
  169. try {
  170. if (!_iteratorNormalCompletion && _iterator.return != null) {
  171. _iterator.return();
  172. }
  173. } finally {
  174. if (_didIteratorError) {
  175. throw _iteratorError;
  176. }
  177. }
  178. }
  179. return transpiledSelectors;
  180. } else if (nodes && nodes.length) {
  181. transformSelectorList(selector.nodes[index], customSelectors);
  182. }
  183. }
  184. return transpiledSelectors;
  185. } // match selectors by difficult-to-separate ends
  186. const withoutSelectorStartMatch = /^(tag|universal)$/;
  187. const withoutSelectorEndMatch = /^(class|id|pseudo|tag|universal)$/;
  188. const isWithoutSelectorStart = node => withoutSelectorStartMatch.test(Object(node).type);
  189. const isWithoutSelectorEnd = node => withoutSelectorEndMatch.test(Object(node).type); // adjust nodes by selector ends (so that .class:--h1 becomes h1.class rather than .classh1)
  190. const adjustNodesBySelectorEnds = (nodes, index) => {
  191. if (index && isWithoutSelectorStart(nodes[index]) && isWithoutSelectorEnd(nodes[index - 1])) {
  192. let safeIndex = index - 1;
  193. while (safeIndex && isWithoutSelectorEnd(nodes[safeIndex])) {
  194. --safeIndex;
  195. }
  196. if (safeIndex < index) {
  197. const node = nodes.splice(index, 1)[0];
  198. nodes.splice(safeIndex, 0, node);
  199. nodes[safeIndex].spaces.before = nodes[safeIndex + 1].spaces.before;
  200. nodes[safeIndex + 1].spaces.before = '';
  201. if (nodes[index]) {
  202. nodes[index].spaces.after = nodes[safeIndex].spaces.after;
  203. nodes[safeIndex].spaces.after = '';
  204. }
  205. }
  206. }
  207. };
  208. var transformRules = ((root, customSelectors, opts) => {
  209. root.walkRules(customPseudoRegExp, rule => {
  210. const selector = parser(selectors => {
  211. transformSelectorList(selectors, customSelectors, opts);
  212. }).processSync(rule.selector);
  213. if (opts.preserve) {
  214. rule.cloneBefore({
  215. selector
  216. });
  217. } else {
  218. rule.selector = selector;
  219. }
  220. });
  221. });
  222. const customPseudoRegExp = /:--[A-z][\w-]*/;
  223. /* Import Custom Selectors from CSS AST
  224. /* ========================================================================== */
  225. function importCustomSelectorsFromCSSAST(root) {
  226. return getCustomSelectors(root);
  227. }
  228. /* Import Custom Selectors from CSS File
  229. /* ========================================================================== */
  230. function importCustomSelectorsFromCSSFile(_x) {
  231. return _importCustomSelectorsFromCSSFile.apply(this, arguments);
  232. }
  233. /* Import Custom Selectors from Object
  234. /* ========================================================================== */
  235. function _importCustomSelectorsFromCSSFile() {
  236. _importCustomSelectorsFromCSSFile = _asyncToGenerator(function* (from) {
  237. const css = yield readFile(path.resolve(from));
  238. const root = postcss.parse(css, {
  239. from: path.resolve(from)
  240. });
  241. return importCustomSelectorsFromCSSAST(root);
  242. });
  243. return _importCustomSelectorsFromCSSFile.apply(this, arguments);
  244. }
  245. function importCustomSelectorsFromObject(object) {
  246. const customSelectors = Object.assign({}, Object(object).customSelectors || Object(object)['custom-selectors']);
  247. for (const key in customSelectors) {
  248. customSelectors[key] = getSelectorsAstFromSelectorsString(customSelectors[key]);
  249. }
  250. return customSelectors;
  251. }
  252. /* Import Custom Selectors from JSON file
  253. /* ========================================================================== */
  254. function importCustomSelectorsFromJSONFile(_x2) {
  255. return _importCustomSelectorsFromJSONFile.apply(this, arguments);
  256. }
  257. /* Import Custom Selectors from JS file
  258. /* ========================================================================== */
  259. function _importCustomSelectorsFromJSONFile() {
  260. _importCustomSelectorsFromJSONFile = _asyncToGenerator(function* (from) {
  261. const object = yield readJSON(path.resolve(from));
  262. return importCustomSelectorsFromObject(object);
  263. });
  264. return _importCustomSelectorsFromJSONFile.apply(this, arguments);
  265. }
  266. function importCustomSelectorsFromJSFile(_x3) {
  267. return _importCustomSelectorsFromJSFile.apply(this, arguments);
  268. }
  269. /* Import Custom Selectors from Sources
  270. /* ========================================================================== */
  271. function _importCustomSelectorsFromJSFile() {
  272. _importCustomSelectorsFromJSFile = _asyncToGenerator(function* (from) {
  273. const object = yield Promise.resolve(require(path.resolve(from)));
  274. return importCustomSelectorsFromObject(object);
  275. });
  276. return _importCustomSelectorsFromJSFile.apply(this, arguments);
  277. }
  278. function importCustomSelectorsFromSources(sources) {
  279. return sources.map(source => {
  280. if (source instanceof Promise) {
  281. return source;
  282. } else if (source instanceof Function) {
  283. return source();
  284. } // read the source as an object
  285. const opts = source === Object(source) ? source : {
  286. from: String(source)
  287. }; // skip objects with custom selectors
  288. if (Object(opts).customSelectors || Object(opts)['custom-selectors']) {
  289. return opts;
  290. } // source pathname
  291. const from = String(opts.from || ''); // type of file being read from
  292. const type = (opts.type || path.extname(from).slice(1)).toLowerCase();
  293. return {
  294. type,
  295. from
  296. };
  297. }).reduce(
  298. /*#__PURE__*/
  299. function () {
  300. var _ref = _asyncToGenerator(function* (customSelectors, source) {
  301. const _ref2 = yield source,
  302. type = _ref2.type,
  303. from = _ref2.from;
  304. if (type === 'ast') {
  305. return Object.assign(customSelectors, importCustomSelectorsFromCSSAST(from));
  306. }
  307. if (type === 'css') {
  308. return Object.assign(customSelectors, (yield importCustomSelectorsFromCSSFile(from)));
  309. }
  310. if (type === 'js') {
  311. return Object.assign(customSelectors, (yield importCustomSelectorsFromJSFile(from)));
  312. }
  313. if (type === 'json') {
  314. return Object.assign(customSelectors, (yield importCustomSelectorsFromJSONFile(from)));
  315. }
  316. return Object.assign(customSelectors, importCustomSelectorsFromObject((yield source)));
  317. });
  318. return function (_x4, _x5) {
  319. return _ref.apply(this, arguments);
  320. };
  321. }(), {});
  322. }
  323. /* Helper utilities
  324. /* ========================================================================== */
  325. const readFile = from => new Promise((resolve, reject) => {
  326. fs.readFile(from, 'utf8', (error, result) => {
  327. if (error) {
  328. reject(error);
  329. } else {
  330. resolve(result);
  331. }
  332. });
  333. });
  334. const readJSON =
  335. /*#__PURE__*/
  336. function () {
  337. var _ref3 = _asyncToGenerator(function* (from) {
  338. return JSON.parse((yield readFile(from)));
  339. });
  340. return function readJSON(_x6) {
  341. return _ref3.apply(this, arguments);
  342. };
  343. }();
  344. /* Import Custom Selectors from CSS File
  345. /* ========================================================================== */
  346. function exportCustomSelectorsToCssFile(_x, _x2) {
  347. return _exportCustomSelectorsToCssFile.apply(this, arguments);
  348. }
  349. /* Import Custom Selectors from JSON file
  350. /* ========================================================================== */
  351. function _exportCustomSelectorsToCssFile() {
  352. _exportCustomSelectorsToCssFile = _asyncToGenerator(function* (to, customSelectors) {
  353. const cssContent = Object.keys(customSelectors).reduce((cssLines, name) => {
  354. cssLines.push(`@custom-selector ${name} ${customSelectors[name]};`);
  355. return cssLines;
  356. }, []).join('\n');
  357. const css = `${cssContent}\n`;
  358. yield writeFile(to, css);
  359. });
  360. return _exportCustomSelectorsToCssFile.apply(this, arguments);
  361. }
  362. function exportCustomSelectorsToJsonFile(_x3, _x4) {
  363. return _exportCustomSelectorsToJsonFile.apply(this, arguments);
  364. }
  365. /* Import Custom Selectors from Common JS file
  366. /* ========================================================================== */
  367. function _exportCustomSelectorsToJsonFile() {
  368. _exportCustomSelectorsToJsonFile = _asyncToGenerator(function* (to, customSelectors) {
  369. const jsonContent = JSON.stringify({
  370. 'custom-selectors': customSelectors
  371. }, null, ' ');
  372. const json = `${jsonContent}\n`;
  373. yield writeFile(to, json);
  374. });
  375. return _exportCustomSelectorsToJsonFile.apply(this, arguments);
  376. }
  377. function exportCustomSelectorsToCjsFile(_x5, _x6) {
  378. return _exportCustomSelectorsToCjsFile.apply(this, arguments);
  379. }
  380. /* Import Custom Selectors from Module JS file
  381. /* ========================================================================== */
  382. function _exportCustomSelectorsToCjsFile() {
  383. _exportCustomSelectorsToCjsFile = _asyncToGenerator(function* (to, customSelectors) {
  384. const jsContents = Object.keys(customSelectors).reduce((jsLines, name) => {
  385. jsLines.push(`\t\t'${escapeForJS(name)}': '${escapeForJS(customSelectors[name])}'`);
  386. return jsLines;
  387. }, []).join(',\n');
  388. const js = `module.exports = {\n\tcustomSelectors: {\n${jsContents}\n\t}\n};\n`;
  389. yield writeFile(to, js);
  390. });
  391. return _exportCustomSelectorsToCjsFile.apply(this, arguments);
  392. }
  393. function exportCustomSelectorsToMjsFile(_x7, _x8) {
  394. return _exportCustomSelectorsToMjsFile.apply(this, arguments);
  395. }
  396. /* Export Custom Selectors to Destinations
  397. /* ========================================================================== */
  398. function _exportCustomSelectorsToMjsFile() {
  399. _exportCustomSelectorsToMjsFile = _asyncToGenerator(function* (to, customSelectors) {
  400. const mjsContents = Object.keys(customSelectors).reduce((mjsLines, name) => {
  401. mjsLines.push(`\t'${escapeForJS(name)}': '${escapeForJS(customSelectors[name])}'`);
  402. return mjsLines;
  403. }, []).join(',\n');
  404. const mjs = `export const customSelectors = {\n${mjsContents}\n};\n`;
  405. yield writeFile(to, mjs);
  406. });
  407. return _exportCustomSelectorsToMjsFile.apply(this, arguments);
  408. }
  409. function exportCustomSelectorsToDestinations(customSelectors, destinations) {
  410. return Promise.all(destinations.map(
  411. /*#__PURE__*/
  412. function () {
  413. var _ref = _asyncToGenerator(function* (destination) {
  414. if (destination instanceof Function) {
  415. yield destination(defaultCustomSelectorsToJSON(customSelectors));
  416. } else {
  417. // read the destination as an object
  418. const opts = destination === Object(destination) ? destination : {
  419. to: String(destination)
  420. }; // transformer for custom selectors into a JSON-compatible object
  421. const toJSON = opts.toJSON || defaultCustomSelectorsToJSON;
  422. if ('customSelectors' in opts) {
  423. // write directly to an object as customSelectors
  424. opts.customSelectors = toJSON(customSelectors);
  425. } else if ('custom-selectors' in opts) {
  426. // write directly to an object as custom-selectors
  427. opts['custom-selectors'] = toJSON(customSelectors);
  428. } else {
  429. // destination pathname
  430. const to = String(opts.to || ''); // type of file being written to
  431. const type = (opts.type || path.extname(opts.to).slice(1)).toLowerCase(); // transformed custom selectors
  432. const customSelectorsJSON = toJSON(customSelectors);
  433. if (type === 'css') {
  434. yield exportCustomSelectorsToCssFile(to, customSelectorsJSON);
  435. }
  436. if (type === 'js') {
  437. yield exportCustomSelectorsToCjsFile(to, customSelectorsJSON);
  438. }
  439. if (type === 'json') {
  440. yield exportCustomSelectorsToJsonFile(to, customSelectorsJSON);
  441. }
  442. if (type === 'mjs') {
  443. yield exportCustomSelectorsToMjsFile(to, customSelectorsJSON);
  444. }
  445. }
  446. }
  447. });
  448. return function (_x9) {
  449. return _ref.apply(this, arguments);
  450. };
  451. }()));
  452. }
  453. /* Helper utilities
  454. /* ========================================================================== */
  455. const defaultCustomSelectorsToJSON = customSelectors => {
  456. return Object.keys(customSelectors).reduce((customSelectorsJSON, key) => {
  457. customSelectorsJSON[key] = String(customSelectors[key]);
  458. return customSelectorsJSON;
  459. }, {});
  460. };
  461. const writeFile = (to, text) => new Promise((resolve, reject) => {
  462. fs.writeFile(to, text, error => {
  463. if (error) {
  464. reject(error);
  465. } else {
  466. resolve();
  467. }
  468. });
  469. });
  470. const escapeForJS = string => string.replace(/\\([\s\S])|(')/g, '\\$1$2').replace(/\n/g, '\\n').replace(/\r/g, '\\r');
  471. var index = postcss.plugin('postcss-custom-selectors', opts => {
  472. // whether to preserve custom selectors and rules using them
  473. const preserve = Boolean(Object(opts).preserve); // sources to import custom selectors from
  474. const importFrom = [].concat(Object(opts).importFrom || []); // destinations to export custom selectors to
  475. const exportTo = [].concat(Object(opts).exportTo || []); // promise any custom selectors are imported
  476. const customSelectorsPromise = importCustomSelectorsFromSources(importFrom);
  477. return (
  478. /*#__PURE__*/
  479. function () {
  480. var _ref = _asyncToGenerator(function* (root) {
  481. const customProperties = Object.assign((yield customSelectorsPromise), getCustomSelectors(root, {
  482. preserve
  483. }));
  484. yield exportCustomSelectorsToDestinations(customProperties, exportTo);
  485. transformRules(root, customProperties, {
  486. preserve
  487. });
  488. });
  489. return function (_x) {
  490. return _ref.apply(this, arguments);
  491. };
  492. }()
  493. );
  494. });
  495. module.exports = index;
  496. //# sourceMappingURL=index.cjs.js.map