Skip to content

Commit ed92ff3

Browse files
committed
separate out validation for the value of an imported prop vs the value of the whole import
1 parent 11969fa commit ed92ff3

File tree

2 files changed

+66
-13
lines changed

2 files changed

+66
-13
lines changed

__tests__/index.spec.js

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ describe('js-to-styles-vars-loader', () => {
5353
});
5454
});
5555

56-
describe('validateExportType', () => {
57-
it ("throws on anything except an object, does not throw otherwise", () => {
56+
describe('validation', () => {
57+
it ("validateExportType() throws on anything except an object, does not throw otherwise", () => {
5858
const areOk = [{}, {a: "foo"}];
5959
const areNotOk = [[], ["a"], "", "123", 123, false, true, null, undefined, NaN];
6060
expect(() => {
@@ -69,7 +69,42 @@ describe('js-to-styles-vars-loader', () => {
6969
},).toThrow();
7070

7171
}
72+
})
73+
74+
it ("validateVariablesValue() throws on nested objects or invalid object property values", () => {
75+
const areOk = [
76+
{a: "foo"},
77+
{a: 100.1},
78+
{a: 100},
79+
{a: ""},
80+
{a: 0},
81+
{a: 0},
82+
{},
83+
];
84+
const areNotOk = [
85+
{a: 1/"bad"},
86+
{b: []},
87+
{c: ["bad"]},
88+
{d: [100.1]},
89+
{e: () => "bad"},
90+
{f: {}},
91+
{g: { b: "bad"} },
92+
{h: "foo", b: {}},
93+
{i: "foo", b: { c: "bad" }},
94+
{j: "foo", b: { c: 100}}
95+
];
96+
expect(() => {
97+
for (const okThing of areOk) {
98+
operator.validateVariablesValue(okThing, "");
99+
}
100+
}).not.toThrow();
101+
for (const notOkThing of areNotOk) {
102+
expect(() => {
103+
operator.validateVariablesValue(notOkThing, "", "");
104+
console.error(`Should have thrown on ${typeof notOkThing} '${JSON.stringify(notOkThing)}'`);
105+
},).toThrow();
72106

107+
}
73108
})
74109
});
75110

@@ -159,18 +194,13 @@ describe('js-to-styles-vars-loader', () => {
159194
addDependency () {}
160195
};
161196
const content = "require('./mocks/colors.js');\n" +
162-
".someClass { color: #fff;}";
163-
164-
const trimmer = (str) => {
165-
return (str.split("\n").filter(a => a).map(s => s.trim()).join(" ")).trim()
166-
};
197+
".someClass { color: #fff; }";
167198

168199
it('inserts vars to styles content', () => {
169200
operator.mergeVarsToContent(content, context, 'less')
170201

171-
expect(trimmer(operator.mergeVarsToContent(content, context, 'less'))).toEqual(trimmer(`
172-
@white: #fff; @black: #000; .someClass { color: #fff;}
173-
`));
202+
expect(operator.mergeVarsToContent(content, context, 'less'))
203+
.toEqual("@white: #fff;\n@black: #000;\n\n.someClass { color: #fff; }");
174204
});
175205

176206
it('call context.addDependecy', () => {

index.js

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,44 @@ const requireReg = /require\s*\((["'])([\w.\/]+)(?:\1)\)((?:\.[\w_-]+)*);?/igm;
77
const operator = {
88

99
validateExportType (data, relativePath) {
10-
if (data === null || typeof data !== "object" || Array.isArray(data)) {
11-
throw new Error(`Value must be a flat object '${relativePath}'`)
10+
if (Object.prototype.toString.call(data) !== '[object Object]') {
11+
throw new Error(`Export must be an object '${relativePath}'`);
1212
}
1313
},
1414

15+
// Ensure it is a flat object with finite number/string values.
16+
validateVariablesValue(value, property, relativePath) {
17+
if (Object.prototype.toString.call(value) !== '[object Object]') {
18+
throw new Error(`Only an object can be converted to style vars (${relativePath}${property})`);
19+
}
20+
21+
const keys = Object.keys(value);
22+
for (const k of keys) {
23+
if (!(
24+
// Define ok types of value (can be output as a style var)
25+
typeof value[k] === "string"
26+
|| (typeof value[k] === "number" && Number.isFinite(value[k]))
27+
)) {
28+
throw new Error(
29+
`Style vars must have a value of type "string" or "number". Only flat objects are supported. ` +
30+
`In: ${relativePath}${property ? ":" : ""}${property}`);
31+
}
32+
}
33+
34+
return true;
35+
},
36+
1537
getVarData (relativePath, property) {
1638
decache(relativePath);
1739
const data = require(relativePath);
1840
if (!data) {
19-
throw new Error(`No data in '${relativePath}'`)
41+
throw new Error(`No data in '${relativePath}'`);
2042
}
2143
this.validateExportType(data, relativePath);
2244
if (property) {
2345
const propVal = squba(data, property);
2446
this.validateExportType(propVal, relativePath);
47+
this.validateVariablesValue(propVal, property, relativePath)
2548
return propVal;
2649
}
2750
return data;

0 commit comments

Comments
 (0)