cli.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #!/usr/bin/env node
  2. const fs = require('fs');
  3. const prefersColorScheme = require('./postcss');
  4. if (process.argv.length < 3) {
  5. console.log([
  6. 'Prefers Color Scheme\n',
  7. ' Transforms CSS with @media (prefers-color-scheme) {}\n',
  8. 'Usage:\n',
  9. ' css-prefers-color-scheme source.css transformed.css',
  10. ' css-prefers-color-scheme --in=source.css --out=transformed.css --opts={}',
  11. ' echo "@media (prefers-color-scheme: dark) {}" | css-prefers-color-scheme\n'
  12. ].join('\n'));
  13. process.exit(0);
  14. }
  15. // get process and plugin options from the command line
  16. const fileRegExp = /^[\w\/.]+$/;
  17. const argRegExp = /^--(\w+)=("|')?(.+)\2$/;
  18. const relaxedJsonRegExp = /(['"])?([a-z0-9A-Z_]+)(['"])?:/g;
  19. const argo = process.argv.slice(2).reduce(
  20. (object, arg) => {
  21. const argMatch = arg.match(argRegExp);
  22. const fileMatch = arg.match(fileRegExp);
  23. if (argMatch) {
  24. object[argMatch[1]] = argMatch[3];
  25. } else if (fileMatch) {
  26. if (object.from === '<stdin>') {
  27. object.from = arg;
  28. } else if (object.to === '<stdout>') {
  29. object.to = arg;
  30. }
  31. }
  32. return object;
  33. },
  34. { from: '<stdin>', to: '<stdout>', opts: 'null' }
  35. );
  36. // get css from command line arguments or stdin
  37. (argo.from === '<stdin>' ? getStdin() : readFile(argo.from))
  38. .then(css => {
  39. const pluginOpts = JSON.parse(argo.opts.replace(relaxedJsonRegExp, '"$2": '));
  40. const processOptions = Object.assign({ from: argo.from, to: argo.to || argo.from }, argo.map ? { map: JSON.parse(argo.map) } : {});
  41. const result = prefersColorScheme.process(css, processOptions, pluginOpts);
  42. if (argo.to === '<stdout>') {
  43. return result.css;
  44. } else {
  45. return writeFile(argo.to, result.css).then(
  46. () => `CSS was written to "${argo.to}"`
  47. )
  48. }
  49. }).then(
  50. result => {
  51. console.log(result);
  52. process.exit(0);
  53. },
  54. error => {
  55. console.error(error);
  56. process.exit(1);
  57. }
  58. );
  59. function readFile(pathname) {
  60. return new Promise((resolve, reject) => {
  61. fs.readFile(pathname, 'utf8', (error, data) => {
  62. if (error) {
  63. reject(error);
  64. } else {
  65. resolve(data);
  66. }
  67. });
  68. });
  69. }
  70. function writeFile(pathname, data) {
  71. return new Promise((resolve, reject) => {
  72. fs.writeFile(pathname, data, (error, content) => {
  73. if (error) {
  74. reject(error);
  75. } else {
  76. resolve(content);
  77. }
  78. });
  79. });
  80. }
  81. function getStdin() {
  82. return new Promise(resolve => {
  83. let data = '';
  84. if (process.stdin.isTTY) {
  85. resolve(data);
  86. } else {
  87. process.stdin.setEncoding('utf8');
  88. process.stdin.on('readable', () => {
  89. let chunk;
  90. while (chunk = process.stdin.read()) {
  91. data += chunk;
  92. }
  93. });
  94. process.stdin.on('end', () => {
  95. resolve(data);
  96. });
  97. }
  98. });
  99. }