Compare commits

..

6 Commits

3 changed files with 56 additions and 4 deletions
+4 -4
View File
@@ -32,8 +32,9 @@ const getNodeParam = (node, name) => {
const controlTargets = getSuperdoughControlTargets();
const getControlData = (control) => {
return controlTargets[control.split('_')[0]];
const getControlData = (control, subControl) => {
const controlNoIdx = control.split('_')[0];
return controlTargets[`${controlNoIdx}_${subControl}`] ?? controlTargets[controlNoIdx];
};
const getRangeForParam = (paramName, currentValue) => {
@@ -59,8 +60,7 @@ const clampWithWaveShaper = (modulator, min, max) => {
};
const getTargetParamsForControl = (control, nodes, subControl) => {
const lookupKey = subControl ? `${control}_${subControl}` : control;
const targetInfo = getControlData(lookupKey) ?? getControlData(control);
const targetInfo = getControlData(control, subControl);
if (!targetInfo) {
errorLogger(
new Error(`Could not find control data for target '${control}'. It may not be modulatable.`),
@@ -42,4 +42,18 @@ describe('transpiler', () => {
[12, 14],
]);
});
it('allows disabling mini', () => {
const code = `/* mini-off */
const randPrefix = Math.random() > 0.5 ? "b" : "s";
const drumPat = \`\${randPrefix}d\`;
// mini-on
s(drumPat).lpf("5000 10000") // make sure mini still runs;
`;
const { output, miniLocations } = transpiler(code, { ...simple, emitMiniLocations: true });
expect(output).not.toContain("m('b'");
expect(output).not.toContain("m('s'");
const cutoffIdx = code.indexOf('5000 10000');
expect(miniLocations).toHaveLength(2);
expect(miniLocations[0][0]).toEqual(cutoffIdx);
});
});
+38
View File
@@ -21,12 +21,15 @@ export function registerLanguage(type, config) {
export function transpiler(input, options = {}) {
const { wrapAsync = false, addReturn = true, emitMiniLocations = true, emitWidgets = true } = options;
const comments = [];
let ast = parse(input, {
ecmaVersion: 2022,
allowAwaitOutsideFunction: true,
locations: true,
onComment: comments,
});
const miniDisableRanges = findMiniDisableRanges(comments, input.length);
let miniLocations = [];
const collectMiniLocations = (value, node) => {
const minilang = languages.get('minilang');
@@ -66,6 +69,9 @@ export function transpiler(input, options = {}) {
return this.replace(tidalWithLocation(raw, offset));
}
if (isBackTickString(node, parent)) {
if (isMiniDisabled(node.start, miniDisableRanges)) {
return;
}
const { quasis } = node;
const { raw } = quasis[0].value;
this.skip();
@@ -73,6 +79,9 @@ export function transpiler(input, options = {}) {
return this.replace(miniWithLocation(raw, node));
}
if (isStringWithDoubleQuotes(node)) {
if (isMiniDisabled(node.start, miniDisableRanges)) {
return;
}
const { value } = node;
this.skip();
emitMiniLocations && collectMiniLocations(value, node);
@@ -327,3 +336,32 @@ function languageWithLocation(name, value, offset) {
optional: false,
};
}
function findMiniDisableRanges(comments, codeEnd) {
const ranges = [];
const stack = []; // used to track on/off pairs
for (const comment of comments) {
const value = comment.value.trim();
if (value.startsWith('mini-off')) {
stack.push(comment.start);
} else if (value.startsWith('mini-on')) {
const start = stack.pop();
ranges.push([start, comment.end]);
}
}
while (stack.length) {
// If no closing mini-on is found, just turn it off until `codeEnd`
const start = stack.pop();
ranges.push([start, codeEnd]);
}
return ranges;
}
function isMiniDisabled(offset, miniDisableRanges) {
for (const [start, end] of miniDisableRanges) {
if (offset >= start && offset < end) {
return true;
}
}
return false;
}