pxtorem-css 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/Readme.md +84 -0
  2. package/app.js +155 -0
  3. package/bin/pxtorem +198 -0
  4. package/package.json +25 -0
package/Readme.md ADDED
@@ -0,0 +1,84 @@
1
+ # pxtorem-css
2
+
3
+ ### A nodejs cli that convert px to rem in any css file
4
+
5
+
6
+ ## Description
7
+ Convert px to rem in css with advanced functionality. pxtorem helps you reduce time when you write css code. This tool build with pure nodejs.
8
+
9
+ Features:
10
+
11
+ * You can convert px to rem in css anywhere within a second.
12
+ * You can choose css directory and also output directory.
13
+ * You can include and exclude css file when convert
14
+ * Even you can ignore css attribute not to convert
15
+ * You can customize options with pxtorem.config.json in your project
16
+
17
+
18
+ ## Installation
19
+
20
+ Locally:
21
+ ```bash
22
+ npm i pxtorem
23
+ ```
24
+
25
+ Globally:
26
+ ```bash
27
+ npm i -g pxtorem
28
+ ```
29
+
30
+ ## Usage
31
+ ```bash
32
+ $ pxtorem [options]
33
+
34
+ Options:
35
+ -init,--init [type] Init pxtorem options json (preset: "pxtorem.config.json")
36
+ -s, --size [type] Select html size (default: "16", preset: "16")
37
+ -d, --dir [type...] Select css directory (default: ["/"], preset: "/")
38
+ -t, --type [type] Select css ext type example: .scss (default: ".css", preset: ".css")
39
+ -i, --ignore [type...] Ignore css attribute (default: [], preset: [])
40
+ -r, --replace [type] For replace file name (default: false, preset: false)
41
+ -o, --output [type] Output directory (default: "", preset: "")
42
+ -in, --include [type...] For include css file path (default: [], preset: [])
43
+ -ex, --exclude [type...] For exclue css file path (default: [], preset: [])
44
+ -c, --config [type] For json config file (default: "", preset: "")
45
+ -h, --help display help for command
46
+
47
+ ```
48
+
49
+ ### Example
50
+ `$ pxtorem` : change all directories css file. <br>
51
+
52
+ `$ pxtorem -d public/css` : change all css file inside public/css dir.<br>
53
+
54
+ `$ pxtorem -d public/css -t .scss` : change all .scss extname file inside public/css dir.<br>
55
+
56
+ `$ pxtorem -d public/css -t .scss -o public/remcss` : change all .scss extname file inside public/css dir and write file to public/remcss dir.<br>
57
+
58
+ `$ pxtorem -d public/css -i box-shadow margin-left padding-left` : change all css file inside public/css dir except box-shadow margin-left padding-left attribute px.<br>
59
+
60
+ `$ pxtorem -d public/css -r my/name/rem/.ext` : change all css filename example: style.css to mystylerem.css<br>
61
+
62
+ `$ pxtorem -c pxtorem.json` : Customize your options with json file in your project folder<br>
63
+
64
+ `$ pxtorem -init` : generate pxtorem.config.json (or you can give custom name) into your project folder<br>
65
+
66
+ ### pxtorem.json Example
67
+ ```bash
68
+ {
69
+ "size": "16",
70
+ "dir": ["public/css"],
71
+ "type": ".css",
72
+ "ignore": ["margin", "padding", "box-shadow"],
73
+ "replace": "{your custom word}/name/{your custom word}/.ext",
74
+ "output": "",
75
+ "include": [],
76
+ "exclude": []
77
+ }
78
+ ```
79
+
80
+ ## Contribution
81
+ If you want to contribute or report any bug, you welcome
82
+
83
+ <br>
84
+ Don't forget to give a star 😍
package/app.js ADDED
@@ -0,0 +1,155 @@
1
+ const chalk = require("chalk");
2
+ const fs = require("fs");
3
+ const path = require("path");
4
+
5
+ function getListOfFile(dir, type, fileList) {
6
+ let files = fs.readdirSync(dir);
7
+ fileList = fileList || [];
8
+ files.forEach((f) => {
9
+ if (!f.startsWith(".")) {
10
+ let filePath = path.join(dir, f);
11
+
12
+ if (fs.statSync(filePath).isDirectory()) {
13
+ fileList = getListOfFile(filePath, type, fileList);
14
+ } else {
15
+ if (f.endsWith(type)) {
16
+ fileList.push(filePath);
17
+ }
18
+ }
19
+ }
20
+ });
21
+ return fileList;
22
+ }
23
+
24
+ function pxtorem(
25
+ { size, dir, type, ignore, replace, output, include, exclude },
26
+ spinner
27
+ ) {
28
+ let finalArr = [];
29
+ dir.forEach((v) => {
30
+ finalArr = finalArr.concat(getListOfFile(v, type));
31
+ });
32
+ let finalPathArr = finalArr.map((v) => path.resolve(v)) || [];
33
+
34
+ if (include.length > 0) {
35
+ include.forEach((v) => {
36
+ if (finalPathArr.indexOf(v) === -1) {
37
+ finalPathArr.push(v);
38
+ }
39
+ });
40
+ }
41
+
42
+ if (exclude.length > 0) {
43
+ exclude.forEach((v) => {
44
+ if (finalPathArr.indexOf(v) !== -1) {
45
+ finalPathArr.splice(finalPathArr.indexOf(v), 1);
46
+ }
47
+ });
48
+ }
49
+ if (finalPathArr.length === 0) {
50
+ spinner.fail(chalk.red("At the end no css file found"));
51
+ process.exit(1);
52
+ }
53
+ finalPathArr.forEach((v) => {
54
+ try {
55
+ let fileName = path.basename(v);
56
+ if (replace) {
57
+ fileName = fileName.replace(
58
+ new RegExp(path.extname(v), "g"),
59
+ ""
60
+ );
61
+ fileName = replace.replace(new RegExp("/name/", "g"), fileName);
62
+
63
+ fileName = fileName.replace(
64
+ new RegExp("/.ext", "g"),
65
+ path.extname(v)
66
+ );
67
+ console.log(fileName);
68
+ }
69
+ const readFileData = fs.readFileSync(v, "utf-8");
70
+ if (!readFileData) {
71
+ throw new Error("Css file empty");
72
+ }
73
+ if (!size) {
74
+ throw new Error("Html size not valid");
75
+ }
76
+ const changeData = changePxToRem(readFileData, size, ignore);
77
+ if (output) {
78
+ const destination = path.join(output, fileName);
79
+
80
+ fs.writeFileSync(destination, changeData, {
81
+ encoding: "utf-8",
82
+ flag: "w",
83
+ });
84
+ } else {
85
+ fs.writeFileSync(v, changeData, {
86
+ encoding: "utf-8",
87
+ flag: "w",
88
+ });
89
+ }
90
+ } catch (error) {
91
+ spinner.fail(chalk.red("Something went wrong", error.message));
92
+ }
93
+ });
94
+ }
95
+
96
+ function changePxToRem(data, size, ignore) {
97
+ const myRegex = /[-]?([a-z]*[-])?[a-z]*?\:.*?.*?px(;)?.*/g;
98
+ const finalRegex =
99
+ /[-]?([a-z]*[-])?[a-z]*?\:.*?([0-9]*[.])?[0-9]*?px+(\s+([0-9]*[.])?[0-9]*?px)*/g;
100
+ const attributeValueRegex =
101
+ /[-]?([a-z]*[-])?[a-z]*?\:.*?([0-9]*[.])?[0-9]*?px/g;
102
+ const valueRegex = /([0-9]*[.])?[0-9]*?px/g;
103
+
104
+ let result = data.match(finalRegex);
105
+
106
+ if (!result) {
107
+ console.log(chalk.red("Match result not found"));
108
+ process.exit(1);
109
+ }
110
+ let filterResult = [];
111
+ if (Array.isArray(ignore) && ignore.length > 0) {
112
+ filterResult = result.filter((res) => {
113
+ for (let i = 0; i < ignore.length; i++) {
114
+ const element = ignore[i];
115
+ if (res.includes(element + ":")) {
116
+ return res;
117
+ }
118
+ }
119
+ });
120
+ }
121
+ let finalResult = result.filter((v) => !filterResult.includes(v)) || [];
122
+
123
+ let valueResult = finalResult.map((v) => {
124
+ return v.match(valueRegex);
125
+ });
126
+
127
+ // result.forEach((v) => {
128
+ // const pxValue = v.slice(0, -2);
129
+ // const valueRegex = new RegExp(`${pxValue}px`, "g");
130
+ // finalData = finalData.replace(
131
+ // valueRegex,
132
+ // `${pxValue / parseFloat(size)}rem`
133
+ // );
134
+ // });
135
+ let finalData = data;
136
+ for (let i = 0; i < finalResult.length; i++) {
137
+ const element = finalResult[i];
138
+ const valueArr = valueResult[i];
139
+ let replaceElement = element;
140
+ for (let j = 0; j < valueArr.length; j++) {
141
+ const value = valueArr[j];
142
+ const pxValue = value.slice(0, -2);
143
+ replaceElement = replaceElement.replace(
144
+ value,
145
+ `${parseFloat(pxValue) / parseFloat(size)}rem`
146
+ );
147
+ }
148
+
149
+ // console.log(replaceElement);
150
+ finalData = finalData.replace(element, replaceElement);
151
+ }
152
+ return finalData;
153
+ }
154
+
155
+ module.exports = pxtorem;
package/bin/pxtorem ADDED
@@ -0,0 +1,198 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const { program, Option } = require("commander");
5
+ const path = require("path");
6
+ const chalk = require("chalk");
7
+ const pxtorem = require("../app");
8
+ const ora = require("ora");
9
+
10
+ const spinner = ora({
11
+ text: chalk.yellow("Converting css px to rem..."),
12
+ color: "yellow",
13
+ });
14
+
15
+ const processDir = process.cwd();
16
+
17
+ program
18
+ .addOption(
19
+ new Option("-init,--init [type]", "Init pxtorem options json").preset(
20
+ "pxtorem.config.json"
21
+ )
22
+ )
23
+ .addOption(
24
+ new Option("-s, --size [type]", "Select html size")
25
+ .preset("16")
26
+ .default("16")
27
+ )
28
+ .addOption(
29
+ new Option("-d, --dir [type...]", "Select css directory")
30
+ .preset("/")
31
+ .default(["/"])
32
+ )
33
+ .addOption(
34
+ new Option("-t, --type [type]", "Select css ext type example: .scss")
35
+ .preset(".css")
36
+ .default(".css")
37
+ )
38
+ .addOption(
39
+ new Option("-i, --ignore [type...]", "Ignore css attribute")
40
+ .preset([])
41
+ .default([])
42
+ )
43
+ .addOption(
44
+ new Option("-r, --replace [type]", "For replace file name")
45
+ .preset(false)
46
+ .default(false)
47
+ )
48
+ .addOption(
49
+ new Option("-o, --output [type]", "Output directory")
50
+ .preset("")
51
+ .default("")
52
+ )
53
+ .addOption(
54
+ new Option("-in, --include [type...]", "For include css file path")
55
+ .preset([])
56
+ .default([])
57
+ )
58
+ .addOption(
59
+ new Option("-ex, --exclude [type...]", "For exclue css file path")
60
+ .preset([])
61
+ .default([])
62
+ )
63
+ .addOption(
64
+ new Option("-c, --config [type]", "For json config file")
65
+ .preset("")
66
+ .default("")
67
+ )
68
+ .parse();
69
+
70
+ let options = program.opts();
71
+
72
+ if (options.init) {
73
+ initFunction(options.init);
74
+ }
75
+ spinner.start();
76
+
77
+ let configObj;
78
+ const currentDir = fs.readdirSync(processDir);
79
+
80
+ if (options.config && options.config.endsWith(".json")) {
81
+ if (currentDir.indexOf(options.config) !== -1) {
82
+ configObj = readConfigFile(options.config);
83
+ }
84
+ } else {
85
+ if (currentDir.indexOf("pxtorem.json") !== -1) {
86
+ configObj = readConfigFile("pxtorem.json");
87
+ }
88
+ if (currentDir.indexOf("pxtorem.config.json") !== -1) {
89
+ configObj = readConfigFile("pxtorem.config.json");
90
+ }
91
+ }
92
+
93
+ function readConfigFile(fileName) {
94
+ try {
95
+ const configFilePath = path.join(processDir, fileName);
96
+ const configfile = fs.readFileSync(configFilePath, "utf-8");
97
+ const toObj = JSON.parse(`${configfile}`);
98
+ if (typeof toObj === "object") {
99
+ return toObj;
100
+ } else {
101
+ return false;
102
+ }
103
+ } catch (error) {
104
+ return false;
105
+ }
106
+ }
107
+
108
+ for (let key in options) {
109
+ if (configObj && configObj.hasOwnProperty(key)) {
110
+ const element = options[key];
111
+ if (Array.isArray(element)) {
112
+ let concatArr = element.concat(configObj[key]);
113
+ let finalArr = [];
114
+ concatArr.forEach((v) => {
115
+ if (finalArr.length === 0) {
116
+ finalArr.push(v);
117
+ } else if (finalArr.indexOf(v) === -1) {
118
+ finalArr.push(v);
119
+ }
120
+ });
121
+ options[key] = finalArr;
122
+ } else {
123
+ options[key] = configObj[key];
124
+ }
125
+ }
126
+ }
127
+
128
+ if (options.replace) {
129
+ const isMatch = options.replace.match(/.*\/name\/.*\/.ext/g);
130
+
131
+ if (!isMatch) {
132
+ spinner.fail(chalk.red("Replace name incorrect please fix this"));
133
+ process.exit(1);
134
+ }
135
+ }
136
+
137
+ options.dir.forEach((v) => {
138
+ const dirPath = path.join(processDir, v);
139
+ if (!fs.existsSync(dirPath)) {
140
+ spinner.fail(chalk.red("Css directories not exist!"));
141
+ process.exit(1);
142
+ }
143
+ });
144
+
145
+ if (options.include.length > 0) {
146
+ options.include.forEach((v) => checkFileExist(v, "Include"));
147
+ options.include = options.include.map((v) => path.resolve(v));
148
+ }
149
+ if (options.exclude.length > 0) {
150
+ options.exclude.forEach((v) => checkFileExist(v, "Exclude"));
151
+ options.exclude = options.exclude.map((v) => path.resolve(v));
152
+ }
153
+
154
+ function checkFileExist(filePath, type) {
155
+ filePath = path.join(processDir, filePath);
156
+ if (!fs.existsSync(filePath)) {
157
+ console.log(chalk.red(`${type} css file not exist`));
158
+ process.exit(1);
159
+ }
160
+ }
161
+
162
+ function checkOutputDir(dir) {
163
+ if (!fs.existsSync(path.join(processDir, dir))) {
164
+ console.log(chalk.red(`Output directory not exist`));
165
+ process.exit(1);
166
+ }
167
+ }
168
+
169
+ if (options.output) {
170
+ checkOutputDir(options.output);
171
+ options.output = path.resolve(options.output);
172
+ }
173
+
174
+ if (options.size && isNaN(options.size)) {
175
+ console.log(chalk.red(`Html size not valid`));
176
+ process.exit(1);
177
+ }
178
+
179
+ function initFunction(name) {
180
+ const initData = `{
181
+ "size": "16",
182
+ "dir": ["public/css"],
183
+ "type": ".css",
184
+ "ignore": ["margin", "padding", "box-shadow"],
185
+ "replace": "{your custom word}/name/{your custom word}/.ext",
186
+ "output": "",
187
+ "include": [],
188
+ "exclude": []
189
+ }`;
190
+ const filePath = path.join(processDir, name);
191
+ fs.writeFileSync(filePath, initData, { encoding: "utf-8", flag: "w" });
192
+ spinner.succeed(chalk.green(`${name} created!`));
193
+ process.exit(1);
194
+ }
195
+
196
+ pxtorem(options, spinner);
197
+
198
+ spinner.succeed(chalk.green("Convert completed. Enjoy (:"));
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "pxtorem-css",
3
+ "version": "1.0.0",
4
+ "description": "A nodejs cli that convert css unit px to rem",
5
+ "main": "app.js",
6
+ "scripts": {},
7
+ "author": "Rashed Iqbal",
8
+ "license": "ISC",
9
+ "bin": {
10
+ "pxtorem": "./bin/pxtorem"
11
+ },
12
+ "keywords": [
13
+ "pxtorem",
14
+ "css",
15
+ "unit",
16
+ "converter",
17
+ "px",
18
+ "rem"
19
+ ],
20
+ "dependencies": {
21
+ "chalk": "^4.1.2",
22
+ "commander": "^9.3.0",
23
+ "ora": "^5.4.1"
24
+ }
25
+ }