Skip to content

Commit e8dc908

Browse files
committed
incorrect shorthand parsing #6
1 parent de70a7e commit e8dc908

File tree

6 files changed

+181
-115
lines changed

6 files changed

+181
-115
lines changed

dist/index-umd-web.js

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,6 +1639,10 @@
16391639
str = options.removeComments ? '' : node.val;
16401640
}
16411641
else if (node.typ == 'Declaration') {
1642+
if (node.val.length == 0) {
1643+
console.error(`invalid declaration`, node);
1644+
return '';
1645+
}
16421646
str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
16431647
}
16441648
else if (node.typ == 'AtRule' && !('chi' in node)) {
@@ -2031,6 +2035,9 @@
20312035
this.pattern = config.pattern.split(/\s/);
20322036
}
20332037
add(declaration) {
2038+
for (const val of declaration.val) {
2039+
Object.defineProperty(val, 'propertyName', { enumerable: false, writable: true, value: declaration.nam });
2040+
}
20342041
if (declaration.nam == this.config.shorthand) {
20352042
this.declarations = new Map;
20362043
this.declarations.set(declaration.nam, declaration);
@@ -2064,7 +2071,7 @@
20642071
i--;
20652072
continue;
20662073
}
2067-
if (matchType(acc[i], props)) {
2074+
if (('propertyName' in acc[i] && acc[i].propertyName == property) || matchType(acc[i], props)) {
20682075
if ('prefix' in props && props.previous != null && !(props.previous in tokens)) {
20692076
return acc;
20702077
}
@@ -2198,10 +2205,12 @@
21982205
}
21992206
else {
22002207
let count = 0;
2208+
let match;
22012209
const separator = this.config.separator;
22022210
const tokens = {};
22032211
// @ts-ignore
2204-
/* const valid: string[] =*/ Object.entries(this.config.properties).reduce((acc, curr) => {
2212+
/* const valid: string[] =*/
2213+
Object.entries(this.config.properties).reduce((acc, curr) => {
22052214
if (!this.declarations.has(curr[0])) {
22062215
if (curr[1].required) {
22072216
acc.push(curr[0]);
@@ -2210,33 +2219,39 @@
22102219
}
22112220
let current = 0;
22122221
const props = this.config.properties[curr[0]];
2213-
const declaration = this.declarations.get(curr[0]);
2214-
// @ts-ignore
2215-
for (const val of (declaration instanceof PropertySet ? [...declaration][0] : declaration).val) {
2216-
if (separator != null && separator.typ == val.typ && eq(separator, val)) {
2217-
current++;
2218-
if (tokens[curr[0]].length == current) {
2219-
tokens[curr[0]].push([]);
2222+
const properties = this.declarations.get(curr[0]);
2223+
for (const declaration of [(properties instanceof PropertySet ? [...properties][0] : properties)]) {
2224+
// @ts-ignore
2225+
for (const val of declaration.val) {
2226+
if (separator != null && separator.typ == val.typ && eq(separator, val)) {
2227+
current++;
2228+
if (tokens[curr[0]].length == current) {
2229+
tokens[curr[0]].push([]);
2230+
}
2231+
continue;
22202232
}
2221-
continue;
2222-
}
2223-
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
2224-
continue;
2225-
}
2226-
if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
2227-
continue;
2228-
}
2229-
if (matchType(val, curr[1])) {
2230-
if (!(curr[0] in tokens)) {
2231-
tokens[curr[0]] = [[]];
2233+
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
2234+
continue;
2235+
}
2236+
if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
2237+
continue;
2238+
}
2239+
match = matchType(val, curr[1]);
2240+
if (isShorthand) {
2241+
isShorthand = match;
2242+
}
2243+
if (('propertyName' in val && val.propertyName == property) || match) {
2244+
if (!(curr[0] in tokens)) {
2245+
tokens[curr[0]] = [[]];
2246+
}
2247+
// is default value
2248+
tokens[curr[0]][current].push(val);
2249+
// continue;
2250+
}
2251+
else {
2252+
acc.push(curr[0]);
2253+
break;
22322254
}
2233-
// is default value
2234-
tokens[curr[0]][current].push(val);
2235-
// continue;
2236-
}
2237-
else {
2238-
acc.push(curr[0]);
2239-
break;
22402255
}
22412256
}
22422257
if (count == 0) {
@@ -2245,7 +2260,7 @@
22452260
return acc;
22462261
}, []);
22472262
count++;
2248-
if (Object.entries(this.config.properties).some(entry => {
2263+
if (!isShorthand || Object.entries(this.config.properties).some(entry => {
22492264
// missing required property
22502265
return entry[1].required && !(entry[0] in tokens);
22512266
}) || !Object.values(tokens).every(v => v.length == count)) {

dist/index.cjs

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,6 +1637,10 @@ function doRender(data, options, reducer, level = 0, indents = []) {
16371637
str = options.removeComments ? '' : node.val;
16381638
}
16391639
else if (node.typ == 'Declaration') {
1640+
if (node.val.length == 0) {
1641+
console.error(`invalid declaration`, node);
1642+
return '';
1643+
}
16401644
str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
16411645
}
16421646
else if (node.typ == 'AtRule' && !('chi' in node)) {
@@ -2029,6 +2033,9 @@ class PropertyMap {
20292033
this.pattern = config.pattern.split(/\s/);
20302034
}
20312035
add(declaration) {
2036+
for (const val of declaration.val) {
2037+
Object.defineProperty(val, 'propertyName', { enumerable: false, writable: true, value: declaration.nam });
2038+
}
20322039
if (declaration.nam == this.config.shorthand) {
20332040
this.declarations = new Map;
20342041
this.declarations.set(declaration.nam, declaration);
@@ -2062,7 +2069,7 @@ class PropertyMap {
20622069
i--;
20632070
continue;
20642071
}
2065-
if (matchType(acc[i], props)) {
2072+
if (('propertyName' in acc[i] && acc[i].propertyName == property) || matchType(acc[i], props)) {
20662073
if ('prefix' in props && props.previous != null && !(props.previous in tokens)) {
20672074
return acc;
20682075
}
@@ -2196,10 +2203,12 @@ class PropertyMap {
21962203
}
21972204
else {
21982205
let count = 0;
2206+
let match;
21992207
const separator = this.config.separator;
22002208
const tokens = {};
22012209
// @ts-ignore
2202-
/* const valid: string[] =*/ Object.entries(this.config.properties).reduce((acc, curr) => {
2210+
/* const valid: string[] =*/
2211+
Object.entries(this.config.properties).reduce((acc, curr) => {
22032212
if (!this.declarations.has(curr[0])) {
22042213
if (curr[1].required) {
22052214
acc.push(curr[0]);
@@ -2208,33 +2217,39 @@ class PropertyMap {
22082217
}
22092218
let current = 0;
22102219
const props = this.config.properties[curr[0]];
2211-
const declaration = this.declarations.get(curr[0]);
2212-
// @ts-ignore
2213-
for (const val of (declaration instanceof PropertySet ? [...declaration][0] : declaration).val) {
2214-
if (separator != null && separator.typ == val.typ && eq(separator, val)) {
2215-
current++;
2216-
if (tokens[curr[0]].length == current) {
2217-
tokens[curr[0]].push([]);
2220+
const properties = this.declarations.get(curr[0]);
2221+
for (const declaration of [(properties instanceof PropertySet ? [...properties][0] : properties)]) {
2222+
// @ts-ignore
2223+
for (const val of declaration.val) {
2224+
if (separator != null && separator.typ == val.typ && eq(separator, val)) {
2225+
current++;
2226+
if (tokens[curr[0]].length == current) {
2227+
tokens[curr[0]].push([]);
2228+
}
2229+
continue;
22182230
}
2219-
continue;
2220-
}
2221-
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
2222-
continue;
2223-
}
2224-
if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
2225-
continue;
2226-
}
2227-
if (matchType(val, curr[1])) {
2228-
if (!(curr[0] in tokens)) {
2229-
tokens[curr[0]] = [[]];
2231+
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
2232+
continue;
2233+
}
2234+
if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
2235+
continue;
2236+
}
2237+
match = matchType(val, curr[1]);
2238+
if (isShorthand) {
2239+
isShorthand = match;
2240+
}
2241+
if (('propertyName' in val && val.propertyName == property) || match) {
2242+
if (!(curr[0] in tokens)) {
2243+
tokens[curr[0]] = [[]];
2244+
}
2245+
// is default value
2246+
tokens[curr[0]][current].push(val);
2247+
// continue;
2248+
}
2249+
else {
2250+
acc.push(curr[0]);
2251+
break;
22302252
}
2231-
// is default value
2232-
tokens[curr[0]][current].push(val);
2233-
// continue;
2234-
}
2235-
else {
2236-
acc.push(curr[0]);
2237-
break;
22382253
}
22392254
}
22402255
if (count == 0) {
@@ -2243,7 +2258,7 @@ class PropertyMap {
22432258
return acc;
22442259
}, []);
22452260
count++;
2246-
if (Object.entries(this.config.properties).some(entry => {
2261+
if (!isShorthand || Object.entries(this.config.properties).some(entry => {
22472262
// missing required property
22482263
return entry[1].required && !(entry[0] in tokens);
22492264
}) || !Object.values(tokens).every(v => v.length == count)) {

dist/lib/parser/declaration/map.js

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ class PropertyMap {
1919
this.pattern = config.pattern.split(/\s/);
2020
}
2121
add(declaration) {
22+
for (const val of declaration.val) {
23+
Object.defineProperty(val, 'propertyName', { enumerable: false, writable: true, value: declaration.nam });
24+
}
2225
if (declaration.nam == this.config.shorthand) {
2326
this.declarations = new Map;
2427
this.declarations.set(declaration.nam, declaration);
@@ -52,7 +55,7 @@ class PropertyMap {
5255
i--;
5356
continue;
5457
}
55-
if (matchType(acc[i], props)) {
58+
if (('propertyName' in acc[i] && acc[i].propertyName == property) || matchType(acc[i], props)) {
5659
if ('prefix' in props && props.previous != null && !(props.previous in tokens)) {
5760
return acc;
5861
}
@@ -186,10 +189,12 @@ class PropertyMap {
186189
}
187190
else {
188191
let count = 0;
192+
let match;
189193
const separator = this.config.separator;
190194
const tokens = {};
191195
// @ts-ignore
192-
/* const valid: string[] =*/ Object.entries(this.config.properties).reduce((acc, curr) => {
196+
/* const valid: string[] =*/
197+
Object.entries(this.config.properties).reduce((acc, curr) => {
193198
if (!this.declarations.has(curr[0])) {
194199
if (curr[1].required) {
195200
acc.push(curr[0]);
@@ -198,33 +203,39 @@ class PropertyMap {
198203
}
199204
let current = 0;
200205
const props = this.config.properties[curr[0]];
201-
const declaration = this.declarations.get(curr[0]);
202-
// @ts-ignore
203-
for (const val of (declaration instanceof PropertySet ? [...declaration][0] : declaration).val) {
204-
if (separator != null && separator.typ == val.typ && eq(separator, val)) {
205-
current++;
206-
if (tokens[curr[0]].length == current) {
207-
tokens[curr[0]].push([]);
206+
const properties = this.declarations.get(curr[0]);
207+
for (const declaration of [(properties instanceof PropertySet ? [...properties][0] : properties)]) {
208+
// @ts-ignore
209+
for (const val of declaration.val) {
210+
if (separator != null && separator.typ == val.typ && eq(separator, val)) {
211+
current++;
212+
if (tokens[curr[0]].length == current) {
213+
tokens[curr[0]].push([]);
214+
}
215+
continue;
208216
}
209-
continue;
210-
}
211-
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
212-
continue;
213-
}
214-
if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
215-
continue;
216-
}
217-
if (matchType(val, curr[1])) {
218-
if (!(curr[0] in tokens)) {
219-
tokens[curr[0]] = [[]];
217+
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
218+
continue;
219+
}
220+
if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
221+
continue;
222+
}
223+
match = matchType(val, curr[1]);
224+
if (isShorthand) {
225+
isShorthand = match;
226+
}
227+
if (('propertyName' in val && val.propertyName == property) || match) {
228+
if (!(curr[0] in tokens)) {
229+
tokens[curr[0]] = [[]];
230+
}
231+
// is default value
232+
tokens[curr[0]][current].push(val);
233+
// continue;
234+
}
235+
else {
236+
acc.push(curr[0]);
237+
break;
220238
}
221-
// is default value
222-
tokens[curr[0]][current].push(val);
223-
// continue;
224-
}
225-
else {
226-
acc.push(curr[0]);
227-
break;
228239
}
229240
}
230241
if (count == 0) {
@@ -233,7 +244,7 @@ class PropertyMap {
233244
return acc;
234245
}, []);
235246
count++;
236-
if (Object.entries(this.config.properties).some(entry => {
247+
if (!isShorthand || Object.entries(this.config.properties).some(entry => {
237248
// missing required property
238249
return entry[1].required && !(entry[0] in tokens);
239250
}) || !Object.values(tokens).every(v => v.length == count)) {

dist/lib/renderer/render.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ function doRender(data, options, reducer, level = 0, indents = []) {
6262
str = options.removeComments ? '' : node.val;
6363
}
6464
else if (node.typ == 'Declaration') {
65+
if (node.val.length == 0) {
66+
console.error(`invalid declaration`, node);
67+
return '';
68+
}
6569
str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
6670
}
6771
else if (node.typ == 'AtRule' && !('chi' in node)) {

0 commit comments

Comments
 (0)