From 369b59d139d32168b18db78e82dc9eb93ff0ddc8 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Tue, 24 Sep 2019 14:42:24 -0500 Subject: [PATCH] feat(scss-generator): add additional types for AST (#4065) * feat(scss-generator): add support for Newline formatting type * feat(scss-generator): add SassValue AST type * feat(scss-generator): add SassFunctionCall AST type * fix(scss-generator): fix SassMixinCall to not prefix $ by default --- .../scss-generator/__tests__/scss-test.js | 23 ++++ .../scss-generator/src/types/definitions.js | 106 +++++++++++++++--- 2 files changed, 114 insertions(+), 15 deletions(-) diff --git a/packages/scss-generator/__tests__/scss-test.js b/packages/scss-generator/__tests__/scss-test.js index ffd261ed8b39..7b4b072e9629 100644 --- a/packages/scss-generator/__tests__/scss-test.js +++ b/packages/scss-generator/__tests__/scss-test.js @@ -414,6 +414,17 @@ describe('@carbon/scss', () => { $test: 1; };`, ], + [ + 'function in assignment', + t.Assignment( + t.Identifier('value'), + t.SassFunctionCall(t.Identifier('map-get'), [ + t.Identifier('map'), + t.SassString('key'), + ]) + ), + `$value: map-get($map, 'key');`, + ], ]; test.each(calls)('%s', (_, ast, expected) => { @@ -515,4 +526,16 @@ describe('@carbon/scss', () => { expect(code.trim()).toEqual(expected.trim()); }); }); + + describe('formatting', () => { + test('newline', () => { + const { code } = generate( + t.StyleSheet([t.Comment('start'), t.Newline(), t.Comment('end')]) + ); + expect(code).toBe(`//start + +//end +`); + }); + }); }); diff --git a/packages/scss-generator/src/types/definitions.js b/packages/scss-generator/src/types/definitions.js index 43decfd23d29..5e497a23bdea 100644 --- a/packages/scss-generator/src/types/definitions.js +++ b/packages/scss-generator/src/types/definitions.js @@ -282,9 +282,63 @@ const SassString = defineType('SassString', { }, }); +// Allow ability to shortcircuit AST builder limitations and embed raw values +// into the Sass source code +const SassValue = defineType('SassValue', { + fields: { + value: { + validate: assertAny, + }, + }, + generate(printer, node) { + printer.token(node.value); + }, +}); + //------------------------------------------------------------------------------- // Calls //------------------------------------------------------------------------------- +const SassFunctionCall = defineType('SassFunctionCall', { + fields: { + id: { + validate: assertType(Identifier), + }, + params: { + optional: true, + validate: () => + arrayOf( + assertOneOf([ + assertType(Identifier), + assertType(SassBoolean), + assertType(SassList), + assertType(SassMap), + assertType(SassNumber), + assertType(SassString), + ]) + ), + }, + }, + generate(printer, node) { + printer.space(); + printer.print(node.id); + printer.token('('); + if (Array.isArray(node.params)) { + for (let i = 0; i < node.params.length; i++) { + const param = node.params[i]; + if (param.type === Identifier.type) { + printer.token('$'); + } + printer.print(param, node); + if (i !== node.params.length - 1) { + printer.token(','); + printer.space(); + } + } + } + printer.token(')'); + }, +}); + const SassMixinCall = defineType('SassMixinCall', { fields: { id: { @@ -317,8 +371,13 @@ const SassMixinCall = defineType('SassMixinCall', { printer.token('('); if (Array.isArray(node.params)) { for (let i = 0; i < node.params.length; i++) { - printer.token('$'); - printer.print(node.params[i], node); + const param = node.params[i]; + + if (param.type === Identifier.type) { + printer.token('$'); + } + + printer.print(param, node); if (i !== node.params.length - 1) { printer.token(','); printer.space(); @@ -465,6 +524,7 @@ const Assignment = defineType('Assignment', { assertType(SassMap), assertType(SassNumber), assertType(SassString), + assertType(SassFunctionCall), ]), }, default: { @@ -663,19 +723,21 @@ const CallExpression = defineType('CallExpression', { const StyleSheet = defineType('StyleSheet', { fields: { children: { - validate: arrayOf( - assertOneOf([ - assertType(Assignment), - assertType(AtRule), - assertType(Comment), - assertType(IfStatement), - assertType(Rule), - assertType(SassFunction), - assertType(SassImport), - assertType(SassMixin), - assertType(SassMixinCall), - ]) - ), + validate: () => + arrayOf( + assertOneOf([ + assertType(Assignment), + assertType(AtRule), + assertType(Comment), + assertType(IfStatement), + assertType(Rule), + assertType(SassFunction), + assertType(SassImport), + assertType(SassMixin), + assertType(SassMixinCall), + assertType(Newline), + ]) + ), }, }, generate(printer, node) { @@ -689,6 +751,15 @@ const StyleSheet = defineType('StyleSheet', { }, }); +//------------------------------------------------------------------------------- +// Formatting +//------------------------------------------------------------------------------- +const Newline = defineType('Newline', { + generate(printer) { + printer.newline(); + }, +}); + module.exports = { Assignment, AssignmentPattern, @@ -707,13 +778,18 @@ module.exports = { SassBoolean, SassColor, SassFunction, + SassFunctionCall, SassImport, SassNumber, SassString, SassList, SassMap, SassMapProperty, + SassValue, SassMixin, SassMixinCall, StyleSheet, + + // Formatting + Newline, };