Skip to content

Commit

Permalink
Merge pull request #405 from Mitcheljager/feat/mixin-param-objects
Browse files Browse the repository at this point in the history
feat: Allow parameter objects to be used for in mixins
  • Loading branch information
Mitcheljager authored Feb 9, 2024
2 parents 9c781bb + 3699956 commit aa23828
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 2 deletions.
10 changes: 8 additions & 2 deletions app/javascript/src/utils/compiler/mixins.js
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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 }"`)

Expand All @@ -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)
Expand All @@ -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] == ";"
Expand Down
30 changes: 30 additions & 0 deletions spec/javascript/utils/compiler/mixins.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down

0 comments on commit aa23828

Please sign in to comment.