From c3fab38acb8e11b43f81e1e7715e8907b2c95ba9 Mon Sep 17 00:00:00 2001 From: Jacob Parker Date: Mon, 21 Nov 2016 11:29:53 +0000 Subject: [PATCH 1/2] Allow omitting quotes for font-family and font-family property in font per spec --- src/grammar.ne | 16 ++++++++++------ src/index.js | 1 + src/index.test.js | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/grammar.ne b/src/grammar.ne index f38efe7..b68081c 100644 --- a/src/grammar.ne +++ b/src/grammar.ne @@ -64,8 +64,8 @@ color return cssColorList.indexOf(name) !== -1 ? name : reject; } %} -_ -> [ \t\n\r]:* {% () => null %} -__ -> [ \t\n\r]:+ {% () => null %} +_ -> [ \t\n\r]:* {% text %} +__ -> [ \t\n\r]:+ {% text %} anyOrder2[a, b] -> $a __ $b {% d => [d[0][0][0], d[2][0][0]] %} @@ -163,17 +163,21 @@ flex return { $merge: { flexGrow, flexShrink, flexBasis } }; } %} +fontFamilyWithIdent + -> (ident (_ ident):* {% text %}) {% text %} +fontFamily + -> "\"" ("\\" . | [^"]):* "\"" {% d => text(d[1]) %} + | "'" ("\\" . | [^']):* "'" {% d => text(d[1]) %} + | fontFamilyWithIdent {% at(0) %} + fontFontStyle -> ("normal" | "italic") {% text %} fontFontVariantCss21 -> "normal" {% () => [] %} | "small-caps" {% () => ['small-caps'] %} fontFontWeight -> ("normal" | "bold" | [1-9] "00") {% text %} -fontFontFamily - -> "\"" ("\\" . | [^"]):* "\"" {% d => text(d[1]) %} - | "'" ("\\" . | [^']):* "'" {% d => text(d[1]) %} font -> anyOrderOptional3AllowNull[fontFontStyle, fontFontVariantCss21, fontFontWeight] _ number (_ "/" _ number):? __ - fontFontFamily {% d => { + fontFamily {% d => { const options = { fontStyle: defaultOptional(d[0][0], 'normal'), fontVariant: defaultOptional(d[0][1], []), diff --git a/src/index.js b/src/index.js index 7f726d6..c6e8909 100644 --- a/src/index.js +++ b/src/index.js @@ -12,6 +12,7 @@ const transforms = [ 'flex', 'flexFlow', 'font', + 'fontFamily', 'fontVariant', 'fontWeight', 'margin', diff --git a/src/index.test.js b/src/index.test.js index f26d4eb..8478be1 100644 --- a/src/index.test.js +++ b/src/index.test.js @@ -260,3 +260,36 @@ it('omits line height if not specified', () => runTest([ fontStyle: 'normal', fontVariant: [], })); + +it('transforms font without quotes', () => runTest([ + ['font', 'bold italic small-caps 16/18 Helvetica Neue'], +], { + fontFamily: 'Helvetica Neue', + fontSize: 16, + fontWeight: 'bold', + fontStyle: 'italic', + fontVariant: ['small-caps'], + lineHeight: 18, +})); + +it('transforms font-family with double quotes', () => runTest([ + ['font-family', '"Helvetica Neue"'], +], { + fontFamily: 'Helvetica Neue', +})); + +it('transforms font-family with single quotes', () => runTest([ + ['font-family', '\'Helvetica Neue\''], +], { + fontFamily: 'Helvetica Neue', +})); + +it('transforms font-family without quotes', () => runTest([ + ['font-family', 'Helvetica Neue'], +], { + fontFamily: 'Helvetica Neue', +})); + +it('does not transform invalid unquoted font-family', () => { + expect(() => transformCss([['font-family', 'Goudy Bookletter 1911']])).toThrow(); +}); From 728621a9c33fd221453ce9ec89545d6e1ab57bf3 Mon Sep 17 00:00:00 2001 From: Jacob Parker Date: Mon, 21 Nov 2016 13:23:25 +0000 Subject: [PATCH 2/2] Fix escape values --- src/grammar.ne | 26 +++++++++++++++++++------- src/index.test.js | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/grammar.ne b/src/grammar.ne index b68081c..fe0bb95 100644 --- a/src/grammar.ne +++ b/src/grammar.ne @@ -4,6 +4,7 @@ const at = index => d => d && d[index]; const pick = indices => d => indices.map(index => d[index]); const text = d => Array.isArray(d) ? d.map(text).join('') : d; + const getCharCode = d => String.fromCharCode(parseInt(text(d[1]), 16)); const transformArg1 = d => ({ [d[0].join('')]: d[2][0] }); const defaultOptional = (value, defaultValue) => value === null ? defaultValue : value; @@ -49,21 +50,35 @@ }; %} +hex -> [a-fA-F0-9] {% text %} + number -> ([0-9]:+) {% d => Number(text(d)) %} angle -> number ("deg" | "rad") {% text %} ident -> ("-":? [_A-Za-z] [_A-Za-z0-9-]:*) {% text %} -# ident -> [^ ]:+ {% text %} color - -> "#" ([a-fA-F0-9]:*) {% text %} + -> "#" (hex:*) {% text %} | ("rgb" | "hsl" | "hsv") ("a":?) "(" ([^)]:+) ")" {% text %} | ([A-Za-z]:+) {% (d, location, reject) => { const name = text(d).toLowerCase(); return cssColorList.indexOf(name) !== -1 ? name : reject; } %} +escapeChar + -> "\\" (hex) " " {% getCharCode %} + | "\\" (hex hex) " " {% getCharCode %} + | "\\" (hex hex hex) " " {% getCharCode %} + | "\\" (hex hex hex hex) " " {% getCharCode %} + | "\\" (hex hex hex hex hex) " " {% getCharCode %} + | "\\" (hex hex hex hex hex hex) {% getCharCode %} + | "\\" [^a-fA-F0-9] {% d => text(d[1]) %} + +string + -> "\"" (escapeChar | [^"\\]):* "\"" {% d => text(d[1]) %} + | "'" (escapeChar | [^'\\]):* "'" {% d => text(d[1]) %} + _ -> [ \t\n\r]:* {% text %} __ -> [ \t\n\r]:+ {% text %} @@ -163,12 +178,9 @@ flex return { $merge: { flexGrow, flexShrink, flexBasis } }; } %} -fontFamilyWithIdent - -> (ident (_ ident):* {% text %}) {% text %} fontFamily - -> "\"" ("\\" . | [^"]):* "\"" {% d => text(d[1]) %} - | "'" ("\\" . | [^']):* "'" {% d => text(d[1]) %} - | fontFamilyWithIdent {% at(0) %} + -> string {% at(0) %} + | (ident (_ ident):*) {% text %} fontFontStyle -> ("normal" | "italic") {% text %} fontFontVariantCss21 -> "normal" {% () => [] %} | "small-caps" {% () => ['small-caps'] %} diff --git a/src/index.test.js b/src/index.test.js index 8478be1..89f556b 100644 --- a/src/index.test.js +++ b/src/index.test.js @@ -290,6 +290,24 @@ it('transforms font-family without quotes', () => runTest([ fontFamily: 'Helvetica Neue', })); +it('transforms font-family with quotes with otherwise invalid values', () => runTest([ + ['font-family', '"Goudy Bookletter 1911"'], +], { + fontFamily: 'Goudy Bookletter 1911', +})); + +it('transforms font-family with quotes with escaped values', () => runTest([ + ['font-family', '"test\\A test"'], +], { + fontFamily: 'test\ntest', +})); + +it('transforms font-family with quotes with escaped quote', () => runTest([ + ['font-family', '"test\\"test"'], +], { + fontFamily: 'test"test', +})); + it('does not transform invalid unquoted font-family', () => { expect(() => transformCss([['font-family', 'Goudy Bookletter 1911']])).toThrow(); });