From 36999566e5dde1ed8930cf205c28b64f73fe5eea Mon Sep 17 00:00:00 2001 From: Mitchel Date: Wed, 7 Feb 2024 01:47:23 +0100 Subject: [PATCH] feat: Allow parameter objects to be used for in mixins --- app/javascript/src/utils/compiler/mixins.js | 10 +++++-- spec/javascript/utils/compiler/mixins.test.js | 30 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/app/javascript/src/utils/compiler/mixins.js b/app/javascript/src/utils/compiler/mixins.js index 3150e369e..3c8205352 100644 --- a/app/javascript/src/utils/compiler/mixins.js +++ b/app/javascript/src/utils/compiler/mixins.js @@ -1,4 +1,5 @@ import { getClosingBracket, replaceBetween, splitArgumentsString } from "../parse" +import { getFirstParameterObject } from "./parameterObjects" export function getMixins(joinedItems) { let mixins = joinedItems.match(/(?<=@mixin\s)[^\s\(]+/g) @@ -69,6 +70,7 @@ export function extractAndInsertMixins(joinedItems) { const full = joinedItems.slice(index, closing + 1) const name = full.match(/(?<=@include\s)(\w+)/)?.[0] const mixin = mixins[name] + const parameterObjectGiven = getFirstParameterObject(full)?.given if (!mixin) throw new Error(`Included a mixin that was not specified: "${ name }"`) @@ -78,7 +80,11 @@ export function extractAndInsertMixins(joinedItems) { continue } const argumentsString = full.slice(argumentsOpeningParen + 1, argumentsClosingParen) - const splitArguments = splitArgumentsString(argumentsString) || [] + let splitArguments = splitArgumentsString(argumentsString) || [] + + // If there is only one argument and that argument is a parameter object we assume the given argument is not for a param. + // This allows us to either insert a single parameter object to be used for the mixin or insert multiple to be used for the params. + if (splitArguments.length === 1 && parameterObjectGiven) splitArguments = [] // eslint-disable-next-line prefer-const let { replaceWith, fullMixin, contents } = replaceContents(joinedItems, index, closing, mixin.content) @@ -87,7 +93,7 @@ export function extractAndInsertMixins(joinedItems) { .map((param, index) => ({ ...param, index })) .sort((p1, p2) => p2.key.length - p1.key.length) .forEach(param => { - replaceWith = replaceWith.replaceAll("Mixin." + param.key, splitArguments[param.index]?.trim() || param.default) + replaceWith = replaceWith.replaceAll("Mixin." + param.key, splitArguments[param.index]?.trim() || parameterObjectGiven?.[param.key] || param.default) }) const closingSemicolon = (!mixin.hasContents || !contents) && joinedItems[closing + 1] == ";" diff --git a/spec/javascript/utils/compiler/mixins.test.js b/spec/javascript/utils/compiler/mixins.test.js index 342b0653b..c9b0cedc1 100644 --- a/spec/javascript/utils/compiler/mixins.test.js +++ b/spec/javascript/utils/compiler/mixins.test.js @@ -215,6 +215,36 @@ describe("mixins.js", () => { expect(result.fullMixin).toEqual(joinedItems) expect(disregardWhitespace(result.replaceWith)).toEqual(disregardWhitespace("Global.slot = 1;")) }) + + it("Should replace Mixin variables with parameter objects if it's given as the only param", () => { + const input = ` + @mixin testMixin(One = 1, Two = 2) { + Mixin.One; + Some Action(Mixin.Two); + } + @include testMixin({ Two: 3 });` + + const expectedOutput = ` + 1; + Some Action(3);` + + expect(disregardWhitespace(extractAndInsertMixins(input))).toBe(disregardWhitespace(expectedOutput)) + }) + + it("Should replace Mixin variables with given parameter objects as parameters if more than one object is given", () => { + const input = ` + @mixin testMixin(One, Two) { + Mixin.One; + Some Action(Mixin.Two); + } + @include testMixin({ One: 1 }, { someVar: someValue });` + + const expectedOutput = ` + { One: 1 }; + Some Action({ someVar: someValue });` + + expect(disregardWhitespace(extractAndInsertMixins(input))).toBe(disregardWhitespace(expectedOutput)) + }) }) describe("getOpeningBracketAt", () => {