Skip to content

Commit f72464a

Browse files
Merge pull request #1 from the-curve-consulting/kishan/support-react-native
Support react-native environment
2 parents 73f7002 + 997daef commit f72464a

File tree

7 files changed

+38
-479
lines changed

7 files changed

+38
-479
lines changed

lib/svgo-node.js

Lines changed: 8 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,14 @@
11
'use strict';
22

3-
const os = require('os');
4-
const fs = require('fs');
5-
const { pathToFileURL } = require('url');
6-
const path = require('path');
73
const { optimize: optimizeAgnostic } = require('./svgo.js');
84

9-
const importConfig = async (configFile) => {
10-
let config;
11-
// at the moment dynamic import may randomly fail with segfault
12-
// to workaround this for some users .cjs extension is loaded
13-
// exclusively with require
14-
if (configFile.endsWith('.cjs')) {
15-
config = require(configFile);
16-
} else {
17-
// dynamic import expects file url instead of path and may fail
18-
// when windows path is provided
19-
const { default: imported } = await import(pathToFileURL(configFile));
20-
config = imported;
21-
}
22-
if (config == null || typeof config !== 'object' || Array.isArray(config)) {
23-
throw Error(`Invalid config file "${configFile}"`);
24-
}
25-
return config;
26-
};
27-
28-
const isFile = async (file) => {
29-
try {
30-
const stats = await fs.promises.stat(file);
31-
return stats.isFile();
32-
} catch {
33-
return false;
34-
}
35-
};
36-
37-
const loadConfig = async (configFile, cwd = process.cwd()) => {
38-
if (configFile != null) {
39-
if (path.isAbsolute(configFile)) {
40-
return await importConfig(configFile);
41-
} else {
42-
return await importConfig(path.join(cwd, configFile));
43-
}
44-
}
45-
let dir = cwd;
46-
// eslint-disable-next-line no-constant-condition
47-
while (true) {
48-
const js = path.join(dir, 'svgo.config.js');
49-
if (await isFile(js)) {
50-
return await importConfig(js);
51-
}
52-
const mjs = path.join(dir, 'svgo.config.mjs');
53-
if (await isFile(mjs)) {
54-
return await importConfig(mjs);
55-
}
56-
const cjs = path.join(dir, 'svgo.config.cjs');
57-
if (await isFile(cjs)) {
58-
return await importConfig(cjs);
59-
}
60-
const parent = path.dirname(dir);
61-
if (dir === parent) {
62-
return null;
63-
}
64-
dir = parent;
65-
}
5+
// eslint-disable-next-line no-unused-vars
6+
const loadConfig = async (_configFile, _cwd) => {
7+
throw new Error(
8+
'Not implemented error. React Native does not support dynamic imports. ' +
9+
'This package (`react-native-svgo`) is meant to be used with react-native, ' +
10+
'if you are not using react-native please consider using the original `https://github.com/svg/svgo` package.'
11+
);
6612
};
6713
exports.loadConfig = loadConfig;
6814

@@ -76,8 +22,7 @@ const optimize = (input, config) => {
7622
return optimizeAgnostic(input, {
7723
...config,
7824
js2svg: {
79-
// platform specific default for end of line
80-
eol: os.EOL === '\r\n' ? 'crlf' : 'lf',
25+
eol: 'lf',
8126
...config.js2svg,
8227
},
8328
});

lib/svgo-node.test.js

Lines changed: 9 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,9 @@
44
* @typedef {import('../lib/types').Plugin} Plugin
55
*/
66

7-
const os = require('os');
8-
const path = require('path');
97
const { optimize, loadConfig } = require('./svgo-node.js');
108

11-
const describeLF = os.EOL === '\r\n' ? describe.skip : describe;
12-
const describeCRLF = os.EOL === '\r\n' ? describe : describe.skip;
13-
14-
describeLF('with LF line-endings', () => {
9+
describe('with LF line-endings', () => {
1510
test('should work', () => {
1611
const svg = `
1712
<?xml version="1.0" encoding="utf-8"?>
@@ -68,144 +63,14 @@ describeLF('with LF line-endings', () => {
6863
});
6964
});
7065

71-
describeCRLF('with CRLF line-endings', () => {
72-
test('should work', () => {
73-
const svg = `
74-
<?xml version="1.0" encoding="utf-8"?>
75-
<svg viewBox="0 0 120 120">
76-
<desc>
77-
Not standard description
78-
</desc>
79-
<circle fill="#ff0000" cx="60" cy="60" r="50"/>
80-
</svg>
81-
`;
82-
const { data } = optimize(svg);
83-
// using toEqual because line endings matter in these tests
84-
expect(data).toEqual(
85-
'<svg viewBox="0 0 120 120"><circle cx="60" cy="60" r="50" fill="red"/></svg>'
86-
);
87-
});
88-
89-
test('should respect config', () => {
90-
const svg = `
91-
<?xml version="1.0" encoding="utf-8"?>
92-
<svg viewBox="0 0 120 120">
93-
<desc>
94-
Not standard description
95-
</desc>
96-
<circle fill="#ff0000" cx="60" cy="60" r="50"/>
97-
</svg>
98-
`;
99-
const { data } = optimize(svg, {
100-
js2svg: { pretty: true, indent: 2 },
101-
});
102-
// using toEqual because line endings matter in these tests
103-
expect(data).toEqual(
104-
'<svg viewBox="0 0 120 120">\r\n <circle cx="60" cy="60" r="50" fill="red"/>\r\n</svg>\r\n'
105-
);
106-
});
107-
108-
test('should respect line-ending config', () => {
109-
const svg = `
110-
<?xml version="1.0" encoding="utf-8"?>
111-
<svg viewBox="0 0 120 120">
112-
<desc>
113-
Not standard description
114-
</desc>
115-
<circle fill="#ff0000" cx="60" cy="60" r="50"/>
116-
</svg>
117-
`;
118-
const { data } = optimize(svg, {
119-
js2svg: { eol: 'lf', pretty: true, indent: 2 },
120-
});
121-
// using toEqual because line endings matter in these tests
122-
expect(data).toEqual(
123-
'<svg viewBox="0 0 120 120">\n <circle fill="red" cx="60" cy="60" r="50"/>\n</svg>\n'
124-
);
125-
});
126-
});
127-
12866
describe('loadConfig', () => {
129-
const cwd = process.cwd();
130-
const fixtures = path.join(cwd, './test/fixtures/config-loader');
131-
132-
test('loads by absolute path', async () => {
133-
expect(await loadConfig(path.join(fixtures, 'one/two/config.js'))).toEqual({
134-
plugins: [],
135-
});
136-
});
137-
138-
test('loads by relative path to cwd', async () => {
139-
const config = await loadConfig('one/two/config.js', fixtures);
140-
expect(config).toEqual({ plugins: [] });
141-
});
142-
143-
test('searches in cwd and up', async () => {
144-
expect(await loadConfig(null, path.join(fixtures, 'one/two'))).toEqual({
145-
plugins: [],
146-
});
147-
expect(
148-
await loadConfig(null, path.join(cwd, './test/fixtures/missing'))
149-
).toEqual(null);
150-
expect(await loadConfig(null, path.join(fixtures, 'mjs'))).toEqual({
151-
plugins: ['mjs'],
152-
});
153-
expect(await loadConfig(null, path.join(fixtures, 'cjs'))).toEqual({
154-
plugins: ['cjs'],
155-
});
156-
});
157-
158-
test('fails when specified config does not exist', async () => {
159-
try {
160-
await loadConfig('{}');
161-
expect.fail('Config is loaded successfully');
162-
} catch (error) {
163-
expect(error.message).toMatch(/Cannot find module/);
164-
}
165-
});
166-
167-
test('fails when exported config not an object', async () => {
168-
try {
169-
await loadConfig(path.join(fixtures, 'invalid-null.js'));
170-
expect.fail('Config is loaded successfully');
171-
} catch (error) {
172-
expect(error.message).toMatch(/Invalid config file/);
173-
}
174-
try {
175-
await loadConfig(path.join(fixtures, 'invalid-array.js'));
176-
expect.fail('Config is loaded successfully');
177-
} catch (error) {
178-
expect(error.message).toMatch(/Invalid config file/);
179-
}
180-
try {
181-
await loadConfig(path.join(fixtures, 'invalid-string.js'));
182-
expect.fail('Config is loaded successfully');
183-
} catch (error) {
184-
expect(error.message).toMatch(/Invalid config file/);
185-
}
186-
});
187-
188-
test('handles runtime errors properly', async () => {
189-
try {
190-
await loadConfig(path.join(fixtures, 'invalid-runtime.js'));
191-
expect.fail('Config is loaded successfully');
192-
} catch (error) {
193-
expect(error.message).toMatch(/plugins is not defined/);
194-
}
195-
try {
196-
await loadConfig(path.join(fixtures, 'invalid-runtime.mjs'));
197-
expect.fail('Config is loaded successfully');
198-
} catch (error) {
199-
expect(error.message).toMatch(/plugins is not defined/);
200-
}
201-
});
202-
203-
test('handles MODULE_NOT_FOUND properly', async () => {
204-
try {
205-
await loadConfig(path.join(fixtures, 'module-not-found.js'));
206-
expect.fail('Config is loaded successfully');
207-
} catch (error) {
208-
expect(error.message).toMatch(/Cannot find module 'unknown-module'/);
209-
}
67+
test('fails with not implemented error', async () => {
68+
await expect(
69+
loadConfig('something', 'something-else')
70+
).rejects.toThrowError(
71+
'Not implemented error. React Native does not support dynamic imports. ' +
72+
'This package (`react-native-svgo`) is meant to be used with react-native, ' +
73+
'if you are not using react-native please consider using the original `https://github.com/svg/svgo` package.'
74+
);
21075
});
21176
});

package.json

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
{
22
"packageManager": "[email protected]",
3-
"name": "svgo",
4-
"version": "3.0.2",
5-
"description": "Nodejs-based tool for optimizing SVG vector graphics files",
3+
"name": "react-native-svgo",
4+
"version": "3.0.2-tccs",
5+
"description": "React Native wrapper for the Nodejs-based tool for optimizing SVG vector graphics files",
66
"license": "MIT",
77
"keywords": [
8+
"react-native",
89
"svgo",
910
"svg",
1011
"optimize",
1112
"minify"
1213
],
13-
"homepage": "https://github.com/svg/svgo",
14+
"homepage": "https://github.com/the-curve-consulting/react-native-svgo",
1415
"bugs": {
15-
"url": "https://github.com/svg/svgo/issues"
16+
"url": "https://github.com/the-curve-consulting/react-native-svgo/issues"
1617
},
1718
"author": {
1819
"name": "Kir Belevich",
@@ -34,11 +35,16 @@
3435
"name": "Bogdan Chadkin",
3536
"email": "[email protected]",
3637
"url": "https://github.com/TrySound"
38+
},
39+
{
40+
"name": "Kishan Jadav",
41+
"email": "[email protected]",
42+
"url": "https://github.com/kishannareshpal"
3743
}
3844
],
3945
"repository": {
4046
"type": "git",
41-
"url": "git://github.com/svg/svgo.git"
47+
"url": "git://github.com/the-curve-consulting/react-native-svgo.git"
4248
},
4349
"funding": {
4450
"type": "opencollective",
@@ -118,6 +124,7 @@
118124
"@types/css-tree": "^2.0.0",
119125
"@types/csso": "^5.0.0",
120126
"@types/jest": "^29.1.1",
127+
"@types/node": "^20.4.2",
121128
"del": "^6.0.0",
122129
"eslint": "^8.24.0",
123130
"jest": "^29.1.2",

0 commit comments

Comments
 (0)