@webstudio-is/react-sdk 0.141.0 → 0.143.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -641,204 +641,11 @@ import { z as z2 } from "zod";
641
641
  import { nanoid } from "nanoid";
642
642
  import { titleCase } from "title-case";
643
643
  import { noCase } from "change-case";
644
+ import {
645
+ encodeDataSourceVariable,
646
+ transpileExpression
647
+ } from "@webstudio-is/sdk";
644
648
  import { StyleValue } from "@webstudio-is/css-engine";
645
-
646
- // src/expression.ts
647
- import jsep from "jsep";
648
- import jsepAssignment from "@jsep-plugin/assignment";
649
- import jsepObject from "@jsep-plugin/object";
650
- jsep.literals["undefined"] = "undefined";
651
- jsep.plugins.register(jsepAssignment);
652
- jsep.plugins.register(jsepObject);
653
- var generateCode = (node, failOnForbidden, options) => {
654
- if (node.type === "Identifier") {
655
- return options.transformIdentifier(node.name, false);
656
- }
657
- if (node.type === "MemberExpression") {
658
- const object = generateCode(node.object, failOnForbidden, options);
659
- const property = node.property;
660
- let propertyString;
661
- if (property.type === "Identifier" && node.computed === false) {
662
- propertyString = property.name;
663
- } else {
664
- propertyString = generateCode(property, failOnForbidden, options);
665
- }
666
- if (node.computed) {
667
- if (options.optional) {
668
- return `${object}?.[${propertyString}]`;
669
- } else {
670
- return `${object}[${propertyString}]`;
671
- }
672
- }
673
- if (options.optional) {
674
- return `${object}?.${propertyString}`;
675
- } else {
676
- return `${object}.${propertyString}`;
677
- }
678
- }
679
- if (node.type === "Literal") {
680
- return node.raw;
681
- }
682
- if (node.type === "UnaryExpression") {
683
- const arg = generateCode(node.argument, failOnForbidden, options);
684
- return `${node.operator}${arg}`;
685
- }
686
- if (node.type === "BinaryExpression") {
687
- const left = generateCode(node.left, failOnForbidden, options);
688
- const right = generateCode(node.right, failOnForbidden, options);
689
- return `${left} ${node.operator} ${right}`;
690
- }
691
- if (node.type === "ArrayExpression") {
692
- const elements = node.elements.map(
693
- (element) => generateCode(element, failOnForbidden, options)
694
- );
695
- return `[${elements.join(", ")}]`;
696
- }
697
- if (node.type === "CallExpression") {
698
- if (failOnForbidden) {
699
- const callee2 = generateCode(node.callee, false, options);
700
- throw Error(`Cannot call "${callee2}"`);
701
- }
702
- const callee = generateCode(node.callee, failOnForbidden, options);
703
- const args = node.arguments.map(
704
- (arg) => generateCode(arg, failOnForbidden, options)
705
- );
706
- return `${callee}(${args.join(", ")})`;
707
- }
708
- if (node.type === "ThisExpression") {
709
- if (failOnForbidden) {
710
- throw Error(`"this" is not supported`);
711
- }
712
- return "this";
713
- }
714
- if (node.type === "ConditionalExpression") {
715
- throw Error("Ternary operator is not supported");
716
- }
717
- if (node.type === "Compound") {
718
- throw Error("Cannot use multiple expressions");
719
- }
720
- if (node.type === "AssignmentExpression") {
721
- if (node.operator !== "=") {
722
- throw Error(`Only "=" assignment operator is supported`);
723
- }
724
- if (options.effectful === false) {
725
- throw Error(`Cannot use assignment in this expression`);
726
- }
727
- const left = generateCode(node.left, failOnForbidden, {
728
- ...options,
729
- // override and mark all identifiers inside of left expression as assignee
730
- transformIdentifier: (id) => options.transformIdentifier(id, true)
731
- });
732
- const right = generateCode(node.right, failOnForbidden, options);
733
- return `${left} ${node.operator} ${right}`;
734
- }
735
- if (node.type === "UpdateExpression") {
736
- throw Error(`"${node.operator}" operator is not supported`);
737
- }
738
- if (node.type === "ObjectExpression") {
739
- const properties = node.properties.map(
740
- (property) => generateCode(property, failOnForbidden, options)
741
- );
742
- return `{${properties.join(", ")}}`;
743
- }
744
- if (node.type === "Property") {
745
- const key = node.key;
746
- let keyString;
747
- if (key.type === "Identifier" && node.computed === false) {
748
- keyString = key.name;
749
- } else {
750
- keyString = generateCode(key, failOnForbidden, options);
751
- }
752
- const value = generateCode(node.value, failOnForbidden, options);
753
- if (node.computed) {
754
- return `[${keyString}]: ${value}`;
755
- }
756
- return `${keyString}: ${value}`;
757
- }
758
- node;
759
- return "";
760
- };
761
- var validateExpression = (code, options) => {
762
- const {
763
- effectful = false,
764
- optional = false,
765
- transformIdentifier = (id) => id
766
- } = options ?? {};
767
- const expression = jsep(code);
768
- return generateCode(expression, true, {
769
- effectful,
770
- optional,
771
- transformIdentifier
772
- });
773
- };
774
- var isLiteralNode = (node) => {
775
- if (node.type === "Literal") {
776
- return true;
777
- }
778
- if (node.type === "ArrayExpression") {
779
- return node.elements.every(isLiteralNode);
780
- }
781
- if (node.type === "ObjectExpression") {
782
- return node.properties.every((property) => {
783
- const key = property.key;
784
- const isIdentifierKey = key.type === "Identifier" && property.computed === false;
785
- const isLiteralKey = key.type === "Literal";
786
- return (isLiteralKey || isIdentifierKey) && isLiteralNode(property.value);
787
- });
788
- }
789
- return false;
790
- };
791
- var isLiteralExpression = (expression) => {
792
- try {
793
- const node = jsep(expression);
794
- return isLiteralNode(node);
795
- } catch {
796
- return false;
797
- }
798
- };
799
- var dataSourceVariablePrefix = "$ws$dataSource$";
800
- var encodeDataSourceVariable = (id) => {
801
- const encoded = id.replaceAll("-", "__DASH__");
802
- return `${dataSourceVariablePrefix}${encoded}`;
803
- };
804
- var decodeDataSourceVariable = (name) => {
805
- if (name.startsWith(dataSourceVariablePrefix)) {
806
- const encoded = name.slice(dataSourceVariablePrefix.length);
807
- return encoded.replaceAll("__DASH__", "-");
808
- }
809
- return;
810
- };
811
- var generateExpression = ({
812
- expression,
813
- dataSources,
814
- usedDataSources,
815
- scope
816
- }) => {
817
- return validateExpression(expression, {
818
- // parse any expression
819
- effectful: true,
820
- // transpile to safely executable member expressions
821
- optional: true,
822
- transformIdentifier: (identifier) => {
823
- const depId = decodeDataSourceVariable(identifier);
824
- const dep = depId ? dataSources.get(depId) : void 0;
825
- if (dep) {
826
- usedDataSources?.set(dep.id, dep);
827
- return scope.getName(dep.id, dep.name);
828
- }
829
- return identifier;
830
- }
831
- });
832
- };
833
- var executeExpression = (expression) => {
834
- try {
835
- const fn = new Function(`return (${expression})`);
836
- return fn();
837
- } catch {
838
- }
839
- };
840
-
841
- // src/embed-template.ts
842
649
  var EmbedTemplateText = z2.object({
843
650
  type: z2.literal("text"),
844
651
  value: z2.string()
@@ -968,8 +775,9 @@ var createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceByR
968
775
  name: prop.name,
969
776
  type: "expression",
970
777
  // replace all references with variable names
971
- value: validateExpression(prop.code, {
972
- transformIdentifier: (ref) => {
778
+ value: transpileExpression({
779
+ expression: prop.code,
780
+ replaceVariable: (ref) => {
973
781
  const id = dataSourceByRef.get(ref)?.id ?? ref;
974
782
  return encodeDataSourceVariable(id);
975
783
  }
@@ -989,11 +797,11 @@ var createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceByR
989
797
  type: "execute",
990
798
  args,
991
799
  // replace all references with variable names
992
- code: validateExpression(value.code, {
993
- effectful: true,
994
- transformIdentifier: (ref) => {
800
+ code: transpileExpression({
801
+ expression: value.code,
802
+ replaceVariable: (ref) => {
995
803
  if (args.includes(ref)) {
996
- return ref;
804
+ return;
997
805
  }
998
806
  const id = dataSourceByRef.get(ref)?.id ?? ref;
999
807
  return encodeDataSourceVariable(id);
@@ -1110,8 +918,9 @@ var createInstancesFromTemplate = (treeTemplate, instances, props, dataSourceByR
1110
918
  parentChildren.push({
1111
919
  type: "expression",
1112
920
  // replace all references with variable names
1113
- value: validateExpression(item.value, {
1114
- transformIdentifier: (ref) => {
921
+ value: transpileExpression({
922
+ expression: item.value,
923
+ replaceVariable: (ref) => {
1115
924
  const id = dataSourceByRef.get(ref)?.id ?? ref;
1116
925
  return encodeDataSourceVariable(id);
1117
926
  }
@@ -1322,31 +1131,13 @@ var getClosestInstance = (instancePath, currentInstance, closestComponent) => {
1322
1131
  }
1323
1132
  };
1324
1133
 
1325
- // src/generator.ts
1326
- var generateUtilsExport = (siteData) => {
1327
- const formsProperties = /* @__PURE__ */ new Map();
1328
- for (const prop of siteData.props.values()) {
1329
- if (prop.type === "string") {
1330
- if (prop.name === "action" || prop.name === "method") {
1331
- let properties = formsProperties.get(prop.instanceId);
1332
- if (properties === void 0) {
1333
- properties = {};
1334
- }
1335
- properties[prop.name] = prop.value;
1336
- formsProperties.set(prop.instanceId, properties);
1337
- }
1338
- }
1339
- }
1340
- const generatedFormsProperties = `export const formsProperties = new Map<string, { method?: string, action?: string }>(${JSON.stringify(
1341
- Array.from(formsProperties.entries())
1342
- )})`;
1343
- return `
1344
- ${generatedFormsProperties}
1345
- `;
1346
- };
1347
-
1348
1134
  // src/component-generator.ts
1349
- import { parseComponentName } from "@webstudio-is/sdk";
1135
+ import {
1136
+ parseComponentName,
1137
+ generateExpression,
1138
+ decodeDataSourceVariable,
1139
+ transpileExpression as transpileExpression2
1140
+ } from "@webstudio-is/sdk";
1350
1141
  var generateAction = ({
1351
1142
  scope,
1352
1143
  prop,
@@ -1358,12 +1149,12 @@ var generateAction = ({
1358
1149
  let assignersCode = "";
1359
1150
  for (const value of prop.value) {
1360
1151
  args = value.args;
1361
- assignersCode += validateExpression(value.code, {
1362
- optional: true,
1363
- effectful: true,
1364
- transformIdentifier: (identifier, assignee) => {
1152
+ assignersCode += transpileExpression2({
1153
+ expression: value.code,
1154
+ executable: true,
1155
+ replaceVariable: (identifier, assignee) => {
1365
1156
  if (args?.includes(identifier)) {
1366
- return identifier;
1157
+ return;
1367
1158
  }
1368
1159
  const depId = decodeDataSourceVariable(identifier);
1369
1160
  const dep = depId ? dataSources.get(depId) : void 0;
@@ -1376,7 +1167,6 @@ var generateAction = ({
1376
1167
  return valueName;
1377
1168
  }
1378
1169
  console.error(`Unknown dependency "${identifier}"`);
1379
- return identifier;
1380
1170
  }
1381
1171
  });
1382
1172
  assignersCode += `
@@ -1687,263 +1477,6 @@ var generateWebstudioComponent = ({
1687
1477
  `;
1688
1478
  return generatedComponent;
1689
1479
  };
1690
-
1691
- // src/resources-generator.ts
1692
- var generateResourcesLoader = ({
1693
- scope,
1694
- page,
1695
- dataSources,
1696
- resources
1697
- }) => {
1698
- let generatedOutput = "";
1699
- let generatedLoaders = "";
1700
- let hasResources = false;
1701
- const usedDataSources = /* @__PURE__ */ new Map();
1702
- for (const dataSource of dataSources.values()) {
1703
- if (dataSource.type === "resource") {
1704
- const resource = resources.get(dataSource.resourceId);
1705
- if (resource === void 0) {
1706
- continue;
1707
- }
1708
- hasResources = true;
1709
- const resourceName = scope.getName(resource.id, dataSource.name);
1710
- generatedOutput += `${resourceName},
1711
- `;
1712
- generatedLoaders += `loadResource({
1713
- `;
1714
- generatedLoaders += `id: "${resource.id}",
1715
- `;
1716
- generatedLoaders += `name: ${JSON.stringify(resource.name)},
1717
- `;
1718
- const url = generateExpression({
1719
- expression: resource.url,
1720
- dataSources,
1721
- usedDataSources,
1722
- scope
1723
- });
1724
- generatedLoaders += `url: ${url},
1725
- `;
1726
- generatedLoaders += `method: "${resource.method}",
1727
- `;
1728
- generatedLoaders += `headers: [
1729
- `;
1730
- for (const header of resource.headers) {
1731
- const value = generateExpression({
1732
- expression: header.value,
1733
- dataSources,
1734
- usedDataSources,
1735
- scope
1736
- });
1737
- generatedLoaders += `{ name: "${header.name}", value: ${value} },
1738
- `;
1739
- }
1740
- generatedLoaders += `],
1741
- `;
1742
- if (resource.body !== void 0 && resource.body.length > 0) {
1743
- const body = generateExpression({
1744
- expression: resource.body,
1745
- dataSources,
1746
- usedDataSources,
1747
- scope
1748
- });
1749
- generatedLoaders += `body: ${body},
1750
- `;
1751
- }
1752
- generatedLoaders += `}),
1753
- `;
1754
- }
1755
- }
1756
- let generatedVariables = "";
1757
- for (const dataSource of usedDataSources.values()) {
1758
- if (dataSource.type === "variable") {
1759
- const name = scope.getName(dataSource.id, dataSource.name);
1760
- const value = JSON.stringify(dataSource.value.value);
1761
- generatedVariables += `let ${name} = ${value}
1762
- `;
1763
- }
1764
- if (dataSource.type === "parameter") {
1765
- if (dataSource.id !== page.systemDataSourceId) {
1766
- continue;
1767
- }
1768
- const name = scope.getName(dataSource.id, dataSource.name);
1769
- generatedVariables += `const ${name} = _props.system
1770
- `;
1771
- }
1772
- }
1773
- let generated = "";
1774
- generated += `import { loadResource, type System } from "@webstudio-is/sdk";
1775
- `;
1776
- generated += `export const loadResources = async (_props: { system: System }) => {
1777
- `;
1778
- generated += generatedVariables;
1779
- if (hasResources) {
1780
- generated += `const [
1781
- `;
1782
- generated += generatedOutput;
1783
- generated += `] = await Promise.all([
1784
- `;
1785
- generated += generatedLoaders;
1786
- generated += `])
1787
- `;
1788
- }
1789
- generated += `return {
1790
- `;
1791
- generated += generatedOutput;
1792
- generated += `} as Record<string, unknown>
1793
- `;
1794
- generated += `}
1795
- `;
1796
- return generated;
1797
- };
1798
-
1799
- // src/page-meta-generator.ts
1800
- import {
1801
- createScope
1802
- } from "@webstudio-is/sdk";
1803
- var generatePageMeta = ({
1804
- globalScope,
1805
- page,
1806
- dataSources
1807
- }) => {
1808
- const localScope = createScope(["system", "resources"]);
1809
- const usedDataSources = /* @__PURE__ */ new Map();
1810
- const titleExpression = generateExpression({
1811
- expression: page.title,
1812
- dataSources,
1813
- usedDataSources,
1814
- scope: localScope
1815
- });
1816
- const descriptionExpression = generateExpression({
1817
- expression: page.meta.description ?? "undefined",
1818
- dataSources,
1819
- usedDataSources,
1820
- scope: localScope
1821
- });
1822
- const excludePageFromSearchExpression = generateExpression({
1823
- expression: page.meta.excludePageFromSearch ?? "undefined",
1824
- dataSources,
1825
- usedDataSources,
1826
- scope: localScope
1827
- });
1828
- const languageExpression = generateExpression({
1829
- expression: page.meta.language ?? "undefined",
1830
- dataSources,
1831
- usedDataSources,
1832
- scope: localScope
1833
- });
1834
- const socialImageAssetIdExpression = JSON.stringify(
1835
- page.meta.socialImageAssetId
1836
- );
1837
- const socialImageUrlExpression = generateExpression({
1838
- expression: page.meta.socialImageUrl ?? "undefined",
1839
- dataSources,
1840
- usedDataSources,
1841
- scope: localScope
1842
- });
1843
- const statusExpression = generateExpression({
1844
- expression: page.meta.status ?? "undefined",
1845
- dataSources,
1846
- usedDataSources,
1847
- scope: localScope
1848
- });
1849
- const redirectExpression = generateExpression({
1850
- expression: page.meta.redirect ?? "undefined",
1851
- dataSources,
1852
- usedDataSources,
1853
- scope: localScope
1854
- });
1855
- let customExpression = "";
1856
- customExpression += `[
1857
- `;
1858
- for (const customMeta of page.meta.custom ?? []) {
1859
- if (customMeta.property.trim().length === 0) {
1860
- continue;
1861
- }
1862
- const propertyExpression = JSON.stringify(customMeta.property);
1863
- const contentExpression = generateExpression({
1864
- expression: customMeta.content,
1865
- dataSources,
1866
- usedDataSources,
1867
- scope: localScope
1868
- });
1869
- customExpression += ` {
1870
- `;
1871
- customExpression += ` property: ${propertyExpression},
1872
- `;
1873
- customExpression += ` content: ${contentExpression},
1874
- `;
1875
- customExpression += ` },
1876
- `;
1877
- }
1878
- customExpression += ` ]`;
1879
- let generated = "";
1880
- generated += `export const getPageMeta = ({
1881
- `;
1882
- generated += ` system,
1883
- `;
1884
- generated += ` resources,
1885
- `;
1886
- generated += `}: {
1887
- `;
1888
- generated += ` system: System;
1889
- `;
1890
- generated += ` resources: Record<string, any>;
1891
- `;
1892
- generated += `}): PageMeta => {
1893
- `;
1894
- for (const dataSource of usedDataSources.values()) {
1895
- if (dataSource.type === "variable") {
1896
- const valueName = localScope.getName(dataSource.id, dataSource.name);
1897
- const initialValueString = JSON.stringify(dataSource.value.value);
1898
- generated += ` let ${valueName} = ${initialValueString}
1899
- `;
1900
- continue;
1901
- }
1902
- if (dataSource.type === "parameter") {
1903
- if (dataSource.id === page.systemDataSourceId) {
1904
- const valueName = localScope.getName(dataSource.id, dataSource.name);
1905
- generated += ` let ${valueName} = system
1906
- `;
1907
- }
1908
- continue;
1909
- }
1910
- if (dataSource.type === "resource") {
1911
- const valueName = localScope.getName(dataSource.id, dataSource.name);
1912
- const resourceName = globalScope.getName(
1913
- dataSource.resourceId,
1914
- dataSource.name
1915
- );
1916
- generated += ` let ${valueName} = resources.${resourceName}
1917
- `;
1918
- continue;
1919
- }
1920
- }
1921
- generated += ` return {
1922
- `;
1923
- generated += ` title: ${titleExpression},
1924
- `;
1925
- generated += ` description: ${descriptionExpression},
1926
- `;
1927
- generated += ` excludePageFromSearch: ${excludePageFromSearchExpression},
1928
- `;
1929
- generated += ` language: ${languageExpression},
1930
- `;
1931
- generated += ` socialImageAssetId: ${socialImageAssetIdExpression},
1932
- `;
1933
- generated += ` socialImageUrl: ${socialImageUrlExpression},
1934
- `;
1935
- generated += ` status: ${statusExpression},
1936
- `;
1937
- generated += ` redirect: ${redirectExpression},
1938
- `;
1939
- generated += ` custom: ${customExpression},
1940
- `;
1941
- generated += ` };
1942
- `;
1943
- generated += `};
1944
- `;
1945
- return generated;
1946
- };
1947
1480
  export {
1948
1481
  EmbedTemplateInstance,
1949
1482
  EmbedTemplateProp,
@@ -1963,20 +1496,13 @@ export {
1963
1496
  createElementsTree,
1964
1497
  createImageValueTransformer,
1965
1498
  createInstanceChildrenElements,
1966
- decodeDataSourceVariable,
1967
1499
  defaultStates,
1968
- encodeDataSourceVariable,
1969
- executeExpression,
1970
1500
  generateCss,
1971
1501
  generateDataFromEmbedTemplate,
1972
- generateExpression,
1973
1502
  generateJsxChildren,
1974
1503
  generateJsxElement,
1975
- generatePageMeta,
1976
1504
  generateRemixParams,
1977
1505
  generateRemixRoute,
1978
- generateResourcesLoader,
1979
- generateUtilsExport,
1980
1506
  generateWebstudioComponent,
1981
1507
  getClosestInstance,
1982
1508
  getIndexWithinAncestorFromComponentProps,
@@ -1986,7 +1512,6 @@ export {
1986
1512
  getStyleRules,
1987
1513
  idAttribute,
1988
1514
  indexAttribute,
1989
- isLiteralExpression,
1990
1515
  namespaceMeta,
1991
1516
  normalizeProps,
1992
1517
  portalComponent,
@@ -1994,6 +1519,5 @@ export {
1994
1519
  showAttribute,
1995
1520
  stateCategories,
1996
1521
  textContentAttribute,
1997
- useResource,
1998
- validateExpression
1522
+ useResource
1999
1523
  };