Skip to content

Commit

Permalink
Fix bug caused by accidentally writing code with un-escaped special c…
Browse files Browse the repository at this point in the history
…haracters
  • Loading branch information
nstrayer committed Aug 29, 2023
1 parent 72da863 commit 2e24127
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { Primatives } from "../../r-parsing";

/**
* Print a primative value to R or python code.
* Handles special cases like special strings and booleans
* @param val
* @returns
*/
export function printPrimative(val: Primatives): string {
switch (typeof val) {
case "string": {
return safeStringPrint(val);
}

default:
return String(val);
}
}

/**
* Escape special characters in a string for R or python code
* @param str The string to escape
* @returns The string with special characters like slashes and quotes escaped
*/
export function safeStringPrint(str: string): string {
// Right now we just use json stringify to escape special characters but in
// the future this may not be enough so we abstract it to a function so we
// don't have to change a million locations
return JSON.stringify(str);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { safeStringPrint } from "./printPrimative";
import { LINE_BREAK_LENGTH, NL_INDENT } from "./utils";

type NamedList = Record<string, string>;
Expand All @@ -12,7 +13,10 @@ function printNamedList(
): string {
const { open_list, close_list, assignment_operator } = options;
const values = Object.keys(vals).map(
(name) => `"${name}" ${assignment_operator} "${vals[name]}"`
(name) =>
`${safeStringPrint(name)} ${assignment_operator} ${safeStringPrint(
vals[name]
)}`
);

// Add 6 for length of `list(` prefix and `)` postfix
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { GeneratedUiDef } from "communication-types/src/MessageToBackend";
import type { ShinyUiNode } from "../ShinyUiNode";
import type { KnownShinyUiNode } from "../uiNodeTypes";

import { printNamedRList } from "./print_named_list";
import { uiNodeTocode } from "./ui_node_to_code";

function uiNodeToRCode(
Expand Down Expand Up @@ -105,6 +106,66 @@ describe("Handles nodes with ui nodes as named arguments", () => {
});
});

describe("Escapes special characters in string nodes", () => {
test("Arrays", () => {
const markdown_node: KnownShinyUiNode = {
id: "markdown",
namedArgs: {
mds: `Here is a slash \\ and here is a double quote "`,
},
};

// prettier-ignore
const expected_result =
`markdown(
mds = c(
"Here is a slash \\\\ and here is a double quote \\""
)
)`;

expect(uiNodeToRCode(markdown_node, { remove_namespace: true }).code).toBe(
expected_result
);
});

test("Named Lists", () => {
const list_with_special_chars = {
slash: "Here's a slash \\",
"double quote": `Here's a double quote "`,
};

// prettier-ignore
const expected_result =
`list(
"slash" = "Here's a slash \\\\",
"double quote" = "Here's a double quote \\""
)`;

expect(printNamedRList(list_with_special_chars)).toBe(expected_result);
});

test("Argument values", () => {
const button_node: KnownShinyUiNode = {
id: "actionButton",
namedArgs: {
inputId: "my_button",
label: `Here is a slash \\ and here is a double quote "`,
},
};

// prettier-ignore
const expected_result =
`actionButton(
inputId = "my_button",
label = "Here is a slash \\\\ and here is a double quote \\""
)`;

expect(uiNodeToRCode(button_node, { remove_namespace: true }).code).toBe(
expected_result
);
});
});

describe("Can turn ShinyUiNode into function call text with formatting", () => {
test("Handles child arguments", () => {
// prettier-ignore
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Primatives } from "../../r-parsing";

import { isNamedList, printNamedRList } from "./print_named_list";
import { printPrimative } from "./printPrimative";
import { NL_INDENT } from "./utils";

export function printRArgumentValue(value: unknown): string {
Expand All @@ -18,12 +19,3 @@ function printRArray(vals: Primatives[]): string {

return `c(${NL_INDENT}${values.join(`,${NL_INDENT}`)}\n)`;
}

function printPrimative(val: Primatives): string {
switch (typeof val) {
case "string":
return `"${val}"`;
default:
return String(val);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Primatives } from "../../r-parsing";

import { isNamedList, printNamedPythonList } from "./print_named_list";
import { printPrimative } from "./printPrimative";
import { NL_INDENT } from "./utils";

export function printPythonArgumentValue(value: unknown): string {
Expand All @@ -18,12 +19,3 @@ export function printPythonArray(vals: Primatives[]): string {

return `[${NL_INDENT}${values.join(`,${NL_INDENT}`)}\n]`;
}

function printPrimative(val: Primatives): string {
switch (typeof val) {
case "string":
return `"${val}"`;
default:
return String(val);
}
}

0 comments on commit 2e24127

Please sign in to comment.