experimental: Allow json in template literals (#3886)

## Description
closes #3872


- [x] - Builder support
- [x] - Publish support

## Steps for reproduction

Example

https://add-json.staging.webstudio.is/builder/8160e16d-5ab4-4249-86de-0c98a64526a3

https://test-json-ki9yj.wstd.work/

## Code Review

- [ ] hi @kof, I need you to do
  - conceptual review (architecture, feature-correctness)
  - detailed review (read every line)
  - test it on preview

## Before requesting a review

- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")

## Before merging

- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env` file
This commit is contained in:
Ivan Starkov authored and GitHub committed 2024-08-11 11:50:18 +03:00
1 parent 403d7b2328
commit 13da170ef4
38 files changed
+888 -173

No files matched your search

@@ -2,7 +2,7 @@ import { beforeEach, expect, test } from "@jest/globals";
import { cleanStores } from "nanostores";
import { createDefaultPages } from "@webstudio-is/project-build";
import { setEnv } from "@webstudio-is/feature-flags";
import type { Instance } from "@webstudio-is/sdk";
import { encodeDataSourceVariable, type Instance } from "@webstudio-is/sdk";
import {
collectionComponent,
textContentAttribute,
@@ -993,3 +993,20 @@ test("prefill default system variable value", () => {
test("compute expression when invalid syntax", () => {
expect(computeExpression("https://github.com", new Map())).toEqual(undefined);
});
test("compute literal expression when variable is json object", () => {
const variableName = "jsonVariable";
const encVariableName = encodeDataSourceVariable(variableName);
const jsonObject = { hello: "world", subObject: { world: "hello" } };
const variables = new Map([[variableName, jsonObject]]);
const expression = "`${" + encVariableName + "}`";
expect(computeExpression(expression, variables)).toEqual(
JSON.stringify(jsonObject)
);
const subObjectExpression = "`${" + encVariableName + ".subObject}`";
expect(computeExpression(subObjectExpression, variables)).toEqual(
JSON.stringify(jsonObject.subObject)
);
});
+11 -1
View File
@@ -9,8 +9,10 @@ import type {
ImageAsset,
} from "@webstudio-is/sdk";
import {
createJsonStringifyProxy,
decodeDataSourceVariable,
encodeDataSourceVariable,
isPlainObject,
transpileExpression,
} from "@webstudio-is/sdk";
import {
@@ -223,7 +225,15 @@ export const computeExpression = (
code += `let ${identifier} = _variables.get("${id}");\n`;
}
code += `return (${transpiled})`;
const result = new Function("_variables", code)(variables);
const proxiedVariables = new Map(
[...variables.entries()].map(([key, value]) => [
key,
isPlainObject(value) ? createJsonStringifyProxy(value) : value,
])
);
const result = new Function("_variables", code)(proxiedVariables);
return result;
} catch {
// empty block