@saltcorn/server 0.9.5-beta.9 → 0.9.5

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/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@saltcorn/server",
3
- "version": "0.9.5-beta.9",
3
+ "version": "0.9.5",
4
4
  "description": "Server app for Saltcorn, open-source no-code platform",
5
5
  "homepage": "https://saltcorn.com",
6
6
  "main": "index.js",
7
7
  "license": "MIT",
8
8
  "dependencies": {
9
9
  "@aws-sdk/client-s3": "^3.451.0",
10
- "@saltcorn/base-plugin": "0.9.5-beta.9",
11
- "@saltcorn/builder": "0.9.5-beta.9",
12
- "@saltcorn/data": "0.9.5-beta.9",
13
- "@saltcorn/admin-models": "0.9.5-beta.9",
14
- "@saltcorn/filemanager": "0.9.5-beta.9",
15
- "@saltcorn/markup": "0.9.5-beta.9",
16
- "@saltcorn/plugins-loader": "0.9.5-beta.9",
17
- "@saltcorn/sbadmin2": "0.9.5-beta.9",
10
+ "@saltcorn/base-plugin": "0.9.5",
11
+ "@saltcorn/builder": "0.9.5",
12
+ "@saltcorn/data": "0.9.5",
13
+ "@saltcorn/admin-models": "0.9.5",
14
+ "@saltcorn/filemanager": "0.9.5",
15
+ "@saltcorn/markup": "0.9.5",
16
+ "@saltcorn/plugins-loader": "0.9.5",
17
+ "@saltcorn/sbadmin2": "0.9.5",
18
18
  "@socket.io/cluster-adapter": "^0.2.1",
19
19
  "@socket.io/sticky": "^1.0.1",
20
20
  "adm-zip": "0.5.10",
@@ -37,6 +37,13 @@ function init_bs5_dropdowns() {
37
37
  }
38
38
  );
39
39
  }
40
+
41
+ function reset_nearest_form(that) {
42
+ const form = $(that).closest("form");
43
+ form.trigger("reset");
44
+ form.find("select").trigger("change");
45
+ }
46
+
40
47
  function add_repeater(nm) {
41
48
  var es = $("div.form-repeat.repeat-" + nm);
42
49
  var e = es.first();
@@ -159,10 +166,18 @@ function apply_showif() {
159
166
  decodeURIComponent(e.attr("data-fetch-options"))
160
167
  );
161
168
  if (window._sc_loglevel > 4) console.log("dynwhere", dynwhere);
162
- const kvToQs = ([k, v]) => {
169
+ const kvToQs = ([k, v], is_or) => {
163
170
  return k === "or" && Array.isArray(v)
164
- ? v.map((v1) => Object.entries(v1).map(kvToQs).join("&")).join("&")
165
- : `${k}=${v[0] === "$" ? rec[v.substring(1)] : v}`;
171
+ ? v
172
+ .map((v1) =>
173
+ Object.entries(v1)
174
+ .map((kv) => kvToQs(kv, true))
175
+ .join("&")
176
+ )
177
+ .join("&")
178
+ : `${k}=${v[0] === "$" ? rec[v.substring(1)] : v}${
179
+ is_or ? "&_or_field=" + k : ""
180
+ }`;
166
181
  };
167
182
  const qss = Object.entries(dynwhere.whereParsed).map(kvToQs);
168
183
  if (dynwhere.dereference) {
@@ -439,8 +454,12 @@ function get_form_record(e_in, select_labels) {
439
454
  } else rec[name] = $this.val();
440
455
  //postprocess
441
456
  if ($this.attr("data-postprocess")) {
442
- const f = new Function("it", "return " + $this.attr("data-postprocess"));
443
- rec[name] = f(rec[name]);
457
+ const f = new Function(
458
+ "it",
459
+ "$e",
460
+ "return " + $this.attr("data-postprocess")
461
+ );
462
+ rec[name] = f(rec[name], $this);
444
463
  }
445
464
  });
446
465
  return rec;
@@ -743,23 +762,58 @@ function initialize_page() {
743
762
  </form>`
744
763
  );
745
764
  });
746
- $("[mobile-img-path]").each(async function () {
747
- if (parent.loadEncodedFile) {
748
- const fileId = $(this).attr("mobile-img-path");
749
- const base64Encoded = await parent.loadEncodedFile(fileId);
750
- this.src = base64Encoded;
751
- }
752
- });
753
- $("[mobile-bg-img-path]").each(async function () {
754
- if (parent.loadEncodedFile) {
755
- const fileId = $(this).attr("mobile-bg-img-path");
756
- if (fileId) {
765
+ if (!isNode) {
766
+ $("[mobile-img-path]").each(async function () {
767
+ if (parent.loadEncodedFile) {
768
+ const fileId = $(this).attr("mobile-img-path");
757
769
  const base64Encoded = await parent.loadEncodedFile(fileId);
758
- this.style.backgroundImage = `url("${base64Encoded}")`;
770
+ this.src = base64Encoded;
759
771
  }
760
- }
761
- });
772
+ });
773
+
774
+ $("[mobile-bg-img-path]").each(async function () {
775
+ if (parent.loadEncodedFile) {
776
+ const fileId = $(this).attr("mobile-bg-img-path");
777
+ if (fileId) {
778
+ const base64Encoded = await parent.loadEncodedFile(fileId);
779
+ this.style.backgroundImage = `url("${base64Encoded}")`;
780
+ }
781
+ }
782
+ });
783
+
784
+ $("a").each(function () {
785
+ let path = $(this).attr("href") || "";
786
+ if (path.startsWith("http")) {
787
+ const url = new URL(path);
788
+ path = `${url.pathname}${url.search}`;
789
+ }
790
+ if (path.startsWith("/view/")) {
791
+ const jThis = $(this);
792
+ const skip = jThis.attr("skip-mobile-adjust");
793
+ if (!skip) {
794
+ jThis.attr("href", `javascript:execLink('${path}')`);
795
+ if (jThis.find("i,img").length === 0 && !jThis.css("color")) {
796
+ jThis.css(
797
+ "color",
798
+ "rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,1))"
799
+ );
800
+ }
801
+ }
802
+ }
803
+ });
762
804
 
805
+ $("img").each(async function () {
806
+ if (parent.loadEncodedFile) {
807
+ const jThis = $(this);
808
+ const src = jThis.attr("src");
809
+ if (src?.startsWith("/files/serve/")) {
810
+ const fileId = src.replace("/files/serve/", "");
811
+ const base64Encoded = await parent.loadEncodedFile(fileId);
812
+ this.src = base64Encoded;
813
+ }
814
+ }
815
+ });
816
+ }
763
817
  function setExplainer(that) {
764
818
  var id = $(that).attr("id") + "_explainer";
765
819
 
@@ -872,6 +926,27 @@ function initialize_page() {
872
926
  .find(".show[rendered='server-side'][type='success']")
873
927
  .removeClass("show");
874
928
  }, 5000);
929
+ $(".lazy-accoordion").on("show.bs.collapse", function (e) {
930
+ const $e = $(e.target).find("[data-sc-view-source]");
931
+ if ($.trim($e.html()) == "") {
932
+ const url = $e.attr("data-sc-view-source");
933
+ $e.html("Loading...");
934
+ $.ajax(url, {
935
+ headers: {
936
+ pjaxpageload: "true",
937
+ localizedstate: "true", //no admin bar
938
+ },
939
+ success: function (res, textStatus, request) {
940
+ $e.html(res);
941
+ initialize_page();
942
+ },
943
+ error: function (res) {
944
+ notifyAlert({ type: "danger", text: res.responseText });
945
+ if ($e.html() === "Loading...") $e.html("");
946
+ },
947
+ });
948
+ }
949
+ });
875
950
  }
876
951
 
877
952
  $(initialize_page);
@@ -1176,8 +1251,10 @@ async function common_done(res, viewname, isWeb = true) {
1176
1251
  await handle(res.notify_success, (text) =>
1177
1252
  notifyAlert({ type: "success", text: text })
1178
1253
  );
1179
- if (res.set_fields && viewname) {
1180
- const form = $(`form[data-viewname="${viewname}"]`);
1254
+ if (res.set_fields && (viewname || res.set_fields._viewname)) {
1255
+ const form = $(
1256
+ `form[data-viewname="${res.set_fields._viewname || viewname}"]`
1257
+ );
1181
1258
  if (form.length === 0 && set_state_fields) {
1182
1259
  // assume this is a filter
1183
1260
  set_state_fields(
@@ -1187,6 +1264,7 @@ async function common_done(res, viewname, isWeb = true) {
1187
1264
  );
1188
1265
  } else {
1189
1266
  Object.keys(res.set_fields).forEach((k) => {
1267
+ if (k === "_viewname") return;
1190
1268
  const input = form.find(
1191
1269
  `input[name=${k}], textarea[name=${k}], select[name=${k}]`
1192
1270
  );
@@ -1195,6 +1273,7 @@ async function common_done(res, viewname, isWeb = true) {
1195
1273
  form.append(
1196
1274
  `<input type="hidden" name="id" value="${res.set_fields[k]}">`
1197
1275
  );
1276
+ reloadEmbeddedEditOwnViews(form, res.set_fields[k]);
1198
1277
  return;
1199
1278
  }
1200
1279
  if (input.attr("type") === "checkbox")
@@ -1259,6 +1338,28 @@ async function common_done(res, viewname, isWeb = true) {
1259
1338
  }
1260
1339
  }
1261
1340
 
1341
+ function reloadEmbeddedEditOwnViews(form, id) {
1342
+ form.find("div[sc-load-on-assign-id]").each(function () {
1343
+ const $e = $(this);
1344
+ const viewname = $e.attr("sc-load-on-assign-id");
1345
+ const newUrl = `/view/${viewname}?id=${id}`;
1346
+ $.ajax(newUrl, {
1347
+ headers: {
1348
+ pjaxpageload: "true",
1349
+ localizedstate: "true", //no admin bar
1350
+ },
1351
+ success: function (res, textStatus, request) {
1352
+ const newE = `<div class="d-inline" data-sc-embed-viewname="${viewname}" data-sc-view-source="${newUrl}">${res}</div>`;
1353
+ $e.replaceWith(newE);
1354
+ initialize_page();
1355
+ },
1356
+ error: function (res) {
1357
+ notifyAlert({ type: "danger", text: res.responseText });
1358
+ },
1359
+ });
1360
+ });
1361
+ }
1362
+
1262
1363
  const repeaterCopyValuesToForm = (form, editor, noTriggerChange) => {
1263
1364
  const vs = JSON.parse(editor.getString());
1264
1365
 
@@ -1551,3 +1652,55 @@ function set_readonly_select(e) {
1551
1652
  const option = options.find((o) => o.value == e.target.value);
1552
1653
  if (option) $disp.val(option.label);
1553
1654
  }
1655
+
1656
+ function close_saltcorn_modal() {
1657
+ $("#scmodal").off("hidden.bs.modal");
1658
+ var myModalEl = document.getElementById("scmodal");
1659
+ if (!myModalEl) return;
1660
+ var modal = bootstrap.Modal.getInstance(myModalEl);
1661
+ if (modal) {
1662
+ if (modal.hide) modal.hide();
1663
+ if (modal.dispose) modal.dispose();
1664
+ }
1665
+ }
1666
+
1667
+ function reload_embedded_view(viewname, new_query_string) {
1668
+ const isNode = getIsNode();
1669
+ const updater = ($e, res) => {
1670
+ $e.html(res);
1671
+ initialize_page();
1672
+ };
1673
+ if (window._sc_loglevel > 4)
1674
+ console.log(
1675
+ "reload_embedded_view",
1676
+ viewname,
1677
+ "found",
1678
+ $(`[data-sc-embed-viewname="${viewname}"]`).length
1679
+ );
1680
+ $(`[data-sc-embed-viewname="${viewname}"]`).each(function () {
1681
+ const $e = $(this);
1682
+ let url = $e.attr("data-sc-local-state") || $e.attr("data-sc-view-source");
1683
+ if (!url) return;
1684
+ if (new_query_string) {
1685
+ url = url.split("?")[0] + "?" + new_query_string;
1686
+ }
1687
+ if (isNode) {
1688
+ $.ajax(url, {
1689
+ headers: {
1690
+ pjaxpageload: "true",
1691
+ localizedstate: "true", //no admin bar
1692
+ },
1693
+ success: function (res, textStatus, request) {
1694
+ updater($e, res);
1695
+ },
1696
+ error: function (res) {
1697
+ notifyAlert({ type: "danger", text: res.responseText });
1698
+ },
1699
+ });
1700
+ } else {
1701
+ runUrl(url).then((html) => {
1702
+ updater($e, html);
1703
+ });
1704
+ }
1705
+ });
1706
+ }
@@ -502,3 +502,7 @@ tr[onclick] {
502
502
  .editStarRating i.fa-star {
503
503
  color: unset;
504
504
  }
505
+
506
+ .modal-header {
507
+ justify-content: space-between;
508
+ }
@@ -154,37 +154,6 @@ $(function () {
154
154
  });
155
155
  });
156
156
 
157
- function reload_embedded_view(viewname, new_query_string) {
158
- if (window._sc_loglevel > 4)
159
- console.log(
160
- "reload_embedded_view",
161
- viewname,
162
- "found",
163
- $(`[data-sc-embed-viewname="${viewname}"]`).length
164
- );
165
- $(`[data-sc-embed-viewname="${viewname}"]`).each(function () {
166
- const $e = $(this);
167
- let url = $e.attr("data-sc-local-state") || $e.attr("data-sc-view-source");
168
- if (!url) return;
169
- if (new_query_string) {
170
- url = url.split("?")[0] + "?" + new_query_string;
171
- }
172
- $.ajax(url, {
173
- headers: {
174
- pjaxpageload: "true",
175
- localizedstate: "true", //no admin bar
176
- },
177
- success: function (res, textStatus, request) {
178
- $e.html(res);
179
- initialize_page();
180
- },
181
- error: function (res) {
182
- notifyAlert({ type: "danger", text: res.responseText });
183
- },
184
- });
185
- });
186
- }
187
-
188
157
  function pjax_to(href, e) {
189
158
  let $modal = $("#scmodal");
190
159
  const inModal = $modal.length && $modal.hasClass("show");
@@ -323,17 +292,6 @@ function globalErrorCatcher(message, source, lineno, colno, error) {
323
292
  });
324
293
  }
325
294
 
326
- function close_saltcorn_modal() {
327
- $("#scmodal").off("hidden.bs.modal");
328
- var myModalEl = document.getElementById("scmodal");
329
- if (!myModalEl) return;
330
- var modal = bootstrap.Modal.getInstance(myModalEl);
331
- if (modal) {
332
- if (modal.hide) modal.hide();
333
- if (modal.dispose) modal.dispose();
334
- }
335
- }
336
-
337
295
  function ensure_modal_exists_and_closed() {
338
296
  if ($("#scmodal").length === 0) {
339
297
  $("body").append(`<div id="scmodal" class="modal">
@@ -450,7 +408,14 @@ function saveAndContinueAsync(e) {
450
408
  });
451
409
  }
452
410
 
453
- function saveAndContinue(e, k) {
411
+ function saveAndContinue(e, k, event) {
412
+ if (
413
+ event &&
414
+ event.target &&
415
+ event.target.classList &&
416
+ event.target.classList.contains("no-form-change")
417
+ )
418
+ return;
454
419
  var form = $(e).closest("form");
455
420
  const valres = form[0].reportValidity();
456
421
  if (!valres) return;
@@ -471,6 +436,7 @@ function saveAndContinue(e, k) {
471
436
  form.append(
472
437
  `<input type="hidden" class="form-control " name="id" value="${res.id}">`
473
438
  );
439
+ reloadEmbeddedEditOwnViews(form, res.id);
474
440
  }
475
441
  common_done(res, form.attr("data-viewname"));
476
442
  },
@@ -515,6 +481,7 @@ function applyViewConfig(e, url, k, event) {
515
481
  cfg[item.name] = item.value;
516
482
  });
517
483
  ajax_indicator(true, e);
484
+ window.savingViewConfig = true;
518
485
  $.ajax(url, {
519
486
  type: "POST",
520
487
  dataType: "json",
@@ -524,9 +491,11 @@ function applyViewConfig(e, url, k, event) {
524
491
  },
525
492
  data: JSON.stringify(cfg),
526
493
  error: function (request) {
494
+ window.savingViewConfig = false;
527
495
  ajax_indicate_error(e, request);
528
496
  },
529
497
  success: function (res) {
498
+ window.savingViewConfig = false;
530
499
  ajax_indicator(false);
531
500
  k && k(res);
532
501
  !k && updateViewPreview();
@@ -575,7 +544,7 @@ function updateViewPreview() {
575
544
  }
576
545
  }
577
546
 
578
- function ajaxSubmitForm(e) {
547
+ function ajaxSubmitForm(e, force_no_reload) {
579
548
  var form = $(e).closest("form");
580
549
  var url = form.attr("action");
581
550
  $.ajax(url, {
@@ -592,11 +561,11 @@ function ajaxSubmitForm(e) {
592
561
  "data-on-close-reload-view"
593
562
  );
594
563
  $("#scmodal").modal("hide");
595
- if (on_close_reload_view) {
564
+ if (!force_no_reload && on_close_reload_view) {
596
565
  const viewE = $(`[data-sc-embed-viewname="${on_close_reload_view}"]`);
597
566
  if (viewE.length) reload_embedded_view(on_close_reload_view);
598
567
  else location.reload();
599
- } else if (!no_reload) location.reload();
568
+ } else if (!force_no_reload && !no_reload) location.reload();
600
569
  else common_done(res, form.attr("data-viewname"));
601
570
  },
602
571
  error: function (request) {
@@ -820,9 +789,9 @@ function build_mobile_app(button) {
820
789
  .filter((option) => !option.hidden)
821
790
  .map((option) => option.value);
822
791
  const pluginsSelect = $("#included-plugins-select-id")[0];
823
- params.includedPlugins = Array.from(pluginsSelect.options)
824
- .filter((option) => !option.hidden)
825
- .map((option) => option.value);
792
+ params.includedPlugins = Array.from(pluginsSelect.options || []).map(
793
+ (option) => option.value
794
+ );
826
795
 
827
796
  if (
828
797
  params.useDocker &&
@@ -858,6 +827,49 @@ function pull_cordova_builder() {
858
827
  });
859
828
  }
860
829
 
830
+ function check_xcodebuild() {
831
+ const handleVersion = (version) => {
832
+ const tokens = version.split(".");
833
+ const majVers = parseInt(tokens[0]);
834
+ const marker = $("#versionMarkerId");
835
+ if (majVers >= 11) {
836
+ marker.removeClass("text-danger");
837
+ marker.addClass("text-success");
838
+ marker.removeClass("fa-times");
839
+ marker.addClass("fa-check");
840
+ } else {
841
+ marker.removeClass("text-success");
842
+ marker.addClass("text-danger");
843
+ marker.removeClass("fa-check");
844
+ marker.addClass("fa-times");
845
+ }
846
+ };
847
+ $.ajax("/admin/mobile-app/check-xcodebuild", {
848
+ type: "GET",
849
+ success: function (res) {
850
+ if (res.installed) {
851
+ $("#xcodebuildStatusId").html(
852
+ `<span>
853
+ installed<i class="ps-2 fas fa-check text-success"></i>
854
+ </span>
855
+ `
856
+ );
857
+ $("#xcodebuildVersionBoxId").removeClass("d-none");
858
+ $("#xcodebuildVersionId").html(` ${res.version}`);
859
+ handleVersion(res.version || "0");
860
+ } else {
861
+ $("#xcodebuildStatusId").html(
862
+ `<span>
863
+ not available<i class="ps-2 fas fa-times text-danger"></i>
864
+ </span>
865
+ `
866
+ );
867
+ $("#xcodebuildVersionBoxId").addClass("d-none");
868
+ }
869
+ },
870
+ });
871
+ }
872
+
861
873
  function check_cordova_builder() {
862
874
  $.ajax("/admin/mobile-app/check-cordova-builder", {
863
875
  type: "GET",
@@ -912,12 +924,14 @@ function move_plugin_to_included() {
912
924
  const opts = $("#excluded-plugins-select-id");
913
925
  $("#included-plugins-select-id").removeAttr("selected");
914
926
  for (const selected of opts.val()) {
915
- const jExclOpt = $(`[id='${selected}_excluded_opt']`);
916
- jExclOpt.attr("hidden", "true");
917
- jExclOpt.removeAttr("selected");
918
- const jInclOpt = $(`[id='${selected}_included_opt']`);
919
- jInclOpt.removeAttr("hidden");
920
- jInclOpt.removeAttr("selected");
927
+ $(`[id='${selected}_excluded_opt']`).remove();
928
+ $("#included-plugins-select-id").append(
929
+ $("<option>", {
930
+ value: selected,
931
+ label: selected,
932
+ id: `${selected}_included_opt`,
933
+ })
934
+ );
921
935
  }
922
936
  }
923
937
 
@@ -925,12 +939,14 @@ function move_plugin_to_excluded() {
925
939
  const opts = $("#included-plugins-select-id");
926
940
  $("#excluded-plugins-select-id").removeAttr("selected");
927
941
  for (const selected of opts.val()) {
928
- const jInclOpt = $(`[id='${selected}_included_opt']`);
929
- jInclOpt.attr("hidden", "true");
930
- jInclOpt.removeAttr("selected");
931
- const jExclOpt = $(`[id='${selected}_excluded_opt']`);
932
- jExclOpt.removeAttr("hidden");
933
- jExclOpt.removeAttr("selected");
942
+ $(`[id='${selected}_included_opt']`).remove();
943
+ $("#excluded-plugins-select-id").append(
944
+ $("<option>", {
945
+ value: selected,
946
+ label: selected,
947
+ id: `${selected}_excluded_opt`,
948
+ })
949
+ );
934
950
  }
935
951
  }
936
952
 
@@ -964,6 +980,10 @@ function join_field_clicked(e, fieldPath) {
964
980
  apply_showif();
965
981
  }
966
982
 
983
+ function execLink(path) {
984
+ window.location.href = `${location.origin}${path}`;
985
+ }
986
+
967
987
  (() => {
968
988
  const e = document.querySelector("[data-sidebar-toggler]");
969
989
  let closed = localStorage.getItem("sidebarClosed") === "true";
@@ -16,6 +16,7 @@ const { eachTenant } = require("@saltcorn/admin-models/models/tenant");
16
16
  const relevantPackages = [
17
17
  "db-common",
18
18
  "common-code",
19
+ "plugins-loader",
19
20
  "postgres",
20
21
  "saltcorn-data",
21
22
  "saltcorn-builder",
@@ -37,6 +38,7 @@ const excludePatterns = [
37
38
  /\.docs/,
38
39
  /migrations/,
39
40
  /.*test.js/,
41
+ /.*test.ts/,
40
42
  ];
41
43
 
42
44
  /**
package/routes/actions.js CHANGED
@@ -307,6 +307,14 @@ const triggerForm = async (req, trigger) => {
307
307
  showIf: { when_trigger: ["API call"] },
308
308
  options: roleOptions,
309
309
  },
310
+ {
311
+ name: "_raw_output",
312
+ label: "Raw Output",
313
+ parent_field: "configuration",
314
+ sublabel: req.__("Do not wrap response in a success object"),
315
+ type: "Bool",
316
+ showIf: { when_trigger: ["API call"] },
317
+ },
310
318
  ],
311
319
  });
312
320
  // if (trigger) {
@@ -450,6 +458,11 @@ router.post(
450
458
  },
451
459
  });
452
460
  } else {
461
+ if (form.values.configuration)
462
+ form.values.configuration = {
463
+ ...trigger.configuration,
464
+ ...form.values.configuration,
465
+ };
453
466
  await Trigger.update(trigger.id, form.values); //{configuration: form.values});
454
467
  req.flash("success", req.__("Action information saved"));
455
468
  res.redirect(`/actions/`);
@@ -662,6 +675,7 @@ router.get(
662
675
  onChange: "saveAndContinue(this)",
663
676
  submitLabel: req.__("Done"),
664
677
  fields: cfgFields,
678
+ ...(action.configFormOptions || {}),
665
679
  });
666
680
  // populate form values
667
681
  form.values = trigger.configuration;
@@ -729,7 +743,9 @@ router.post(
729
743
  },
730
744
  });
731
745
  } else {
732
- await Trigger.update(trigger.id, { configuration: form.values });
746
+ await Trigger.update(trigger.id, {
747
+ configuration: { ...trigger.configuration, ...form.values },
748
+ });
733
749
  if (req.xhr) {
734
750
  res.json({ success: "ok" });
735
751
  return;