@flourish/sdk 5.2.0 → 5.2.2
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/RELEASE_NOTES.md +7 -0
- package/common/embed/embedding.d.ts +1 -1
- package/common/embed/embedding.js +22 -1
- package/common/package.json +5 -1
- package/common/tsconfig.sdk.tsbuildinfo +1 -1
- package/common/utils/data.d.ts +1 -1
- package/common/utils/data.js +6 -0
- package/common/utils/state.d.ts +7 -7
- package/common/utils/state.js +14 -16
- package/lib/cmd/publish.js +0 -1
- package/lib/cmd/upgrade/1-convert-config-to-yaml.js +0 -3
- package/lib/common.js +1 -4
- package/lib/sdk.js +0 -5
- package/package.json +3 -2
- package/rollup.config.mjs +1 -1
- package/server/index.js +1 -3
- package/server/views/default_template_index.html +1 -0
- package/server/views/index.html +17 -1
- package/site/embedded.js +1 -1
- package/site/images/canva.svg +27 -0
- package/site/images/icon-calendar.svg +3 -0
- package/site/images/icon-number.svg +5 -0
- package/site/images/icon-private.svg +1 -1
- package/site/images/icon-text.svg +3 -0
- package/site/images/icon-viewable.svg +1 -1
- package/site/script.js +3 -3
- package/site/sdk.css +1 -1
- package/skeleton/package.json +4 -0
- package/test/lib/sdk.js +0 -1
- package/test/lib/validate_config.js +33 -33
- package/server/columns.js +0 -201
- package/server/data.js +0 -327
- package/server/json.js +0 -66
package/skeleton/package.json
CHANGED
package/test/lib/sdk.js
CHANGED
|
@@ -45,11 +45,11 @@ describe("validate_config", function() {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
function bindingPlus(o) {
|
|
48
|
-
return metadataPlus({ data: [
|
|
48
|
+
return metadataPlus({ data: [Object.assign({}, binding, o)] });
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
function settingPlus(o, other, more_settings=[]) {
|
|
52
|
-
return metadataPlus(Object.assign({ settings: [
|
|
52
|
+
return metadataPlus(Object.assign({ settings: [Object.assign({}, setting_foo, o), setting_bar].concat(more_settings) }, other));
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
function testBoolean(name) {
|
|
@@ -325,30 +325,30 @@ describe("validate_config", function() {
|
|
|
325
325
|
"template.yml: “build.foo.files” must be an array");
|
|
326
326
|
});
|
|
327
327
|
it("should reject a null file", function() {
|
|
328
|
-
expectFailure(metadataPlus({ build: { foo: { script: "", files: [
|
|
328
|
+
expectFailure(metadataPlus({ build: { foo: { script: "", files: [null] } } }),
|
|
329
329
|
"template.yml: the entries of “build.foo.files” must be strings");
|
|
330
330
|
});
|
|
331
331
|
it("should reject an undefined file", function() {
|
|
332
|
-
expectFailure(metadataPlus({ build: { foo: { script: "", files: [
|
|
332
|
+
expectFailure(metadataPlus({ build: { foo: { script: "", files: [undefined] } } }),
|
|
333
333
|
"template.yml: the entries of “build.foo.files” must be strings");
|
|
334
334
|
});
|
|
335
335
|
it("should reject a numeric file", function() {
|
|
336
|
-
expectFailure(metadataPlus({ build: { foo: { script: "", files: [
|
|
336
|
+
expectFailure(metadataPlus({ build: { foo: { script: "", files: [23] } } }),
|
|
337
337
|
"template.yml: the entries of “build.foo.files” must be strings");
|
|
338
338
|
});
|
|
339
339
|
it("should reject a true file", function() {
|
|
340
|
-
expectFailure(metadataPlus({ build: { foo: { script: "", files: [
|
|
340
|
+
expectFailure(metadataPlus({ build: { foo: { script: "", files: [true] } } }),
|
|
341
341
|
"template.yml: the entries of “build.foo.files” must be strings");
|
|
342
342
|
});
|
|
343
343
|
it("should reject a false file", function() {
|
|
344
|
-
expectFailure(metadataPlus({ build: { foo: { script: "", files: [
|
|
344
|
+
expectFailure(metadataPlus({ build: { foo: { script: "", files: [false] } } }),
|
|
345
345
|
"template.yml: the entries of “build.foo.files” must be strings");
|
|
346
346
|
});
|
|
347
347
|
it("should accept a string file", function() {
|
|
348
|
-
expectSuccess(metadataPlus({ build: { foo: { script: "", files: [
|
|
348
|
+
expectSuccess(metadataPlus({ build: { foo: { script: "", files: [""] } } }));
|
|
349
349
|
});
|
|
350
350
|
it("should accept two strings", function() {
|
|
351
|
-
expectSuccess(metadataPlus({ build: { foo: { script: "", files: [
|
|
351
|
+
expectSuccess(metadataPlus({ build: { foo: { script: "", files: ["one", "two"] } } }));
|
|
352
352
|
});
|
|
353
353
|
|
|
354
354
|
it("should reject a null directory", function() {
|
|
@@ -410,23 +410,23 @@ describe("validate_config", function() {
|
|
|
410
410
|
type = binding.type;
|
|
411
411
|
|
|
412
412
|
it("should require name", function() {
|
|
413
|
-
expectFailure(metadataPlus({ data: [
|
|
413
|
+
expectFailure(metadataPlus({ data: [{ dataset, key, type }] }),
|
|
414
414
|
"template.yml data binding must specify a name");
|
|
415
415
|
});
|
|
416
416
|
it("should require dataset", function() {
|
|
417
|
-
expectFailure(metadataPlus({ data: [
|
|
417
|
+
expectFailure(metadataPlus({ data: [{ name, key, type }] }),
|
|
418
418
|
"template.yml data binding “My binding” must specify a dataset");
|
|
419
419
|
});
|
|
420
420
|
it("should require key", function() {
|
|
421
|
-
expectFailure(metadataPlus({ data: [
|
|
421
|
+
expectFailure(metadataPlus({ data: [{ name, dataset, type }] }),
|
|
422
422
|
"template.yml data binding “My binding” must specify a key");
|
|
423
423
|
});
|
|
424
424
|
it("should require type", function() {
|
|
425
|
-
expectFailure(metadataPlus({ data: [
|
|
425
|
+
expectFailure(metadataPlus({ data: [{ name, dataset, key }] }),
|
|
426
426
|
"template.yml data binding “My binding” must specify a type");
|
|
427
427
|
});
|
|
428
428
|
it("should require column for non-optional column bindings", function() {
|
|
429
|
-
expectFailure(metadataPlus({ data: [
|
|
429
|
+
expectFailure(metadataPlus({ data: [{ name, dataset, key, type }] }),
|
|
430
430
|
"template.yml non-optional data binding “My binding” must specify column");
|
|
431
431
|
});
|
|
432
432
|
it("should accept name/dataset/key/type=column/column", function() {
|
|
@@ -528,17 +528,17 @@ describe("validate_config", function() {
|
|
|
528
528
|
expectSuccess(bindingPlus({ optional: false }));
|
|
529
529
|
});
|
|
530
530
|
it("should require column if optional is false", function() {
|
|
531
|
-
expectFailure(metadataPlus({ data: [
|
|
531
|
+
expectFailure(metadataPlus({ data: [{ name, dataset, key, type, optional: false }] }),
|
|
532
532
|
"template.yml non-optional data binding “My binding” must specify column");
|
|
533
533
|
});
|
|
534
534
|
|
|
535
535
|
it("should reject duplicates", function() {
|
|
536
|
-
expectFailure(metadataPlus({ data: [
|
|
536
|
+
expectFailure(metadataPlus({ data: [binding, binding] }),
|
|
537
537
|
"template.yml: there is more than one data binding with dataset “dataset” and key “key”");
|
|
538
538
|
});
|
|
539
539
|
|
|
540
540
|
it("should ignore headings", function() {
|
|
541
|
-
expectSuccess(metadataPlus({ data: [
|
|
541
|
+
expectSuccess(metadataPlus({ data: ["Heading", binding] }));
|
|
542
542
|
});
|
|
543
543
|
});
|
|
544
544
|
|
|
@@ -571,19 +571,19 @@ describe("validate_config", function() {
|
|
|
571
571
|
});
|
|
572
572
|
|
|
573
573
|
it("should require property", function() {
|
|
574
|
-
expectFailure(metadataPlus({ settings: [
|
|
574
|
+
expectFailure(metadataPlus({ settings: [{ name: "Foo", type: "string" }] }),
|
|
575
575
|
"template.yml setting must specify a property:");
|
|
576
576
|
});
|
|
577
577
|
it("should require type", function() {
|
|
578
|
-
expectFailure(metadataPlus({ settings: [
|
|
578
|
+
expectFailure(metadataPlus({ settings: [{ name: "Foo", property: "foo" }] }),
|
|
579
579
|
"template.yml setting “foo” must specify a type:");
|
|
580
580
|
});
|
|
581
581
|
it("should require name", function() {
|
|
582
|
-
expectFailure(metadataPlus({ settings: [
|
|
582
|
+
expectFailure(metadataPlus({ settings: [{ property: "foo", type: "string" }] }),
|
|
583
583
|
"template.yml setting “foo” must specify a name:");
|
|
584
584
|
});
|
|
585
585
|
it("should not require name if choices are specified", function() {
|
|
586
|
-
expectSuccess(metadataPlus({ settings: [
|
|
586
|
+
expectSuccess(metadataPlus({ settings: [{ property: "foo", type: "string", choices: [] }] }));
|
|
587
587
|
});
|
|
588
588
|
|
|
589
589
|
describe("optional settings", function() {
|
|
@@ -828,43 +828,43 @@ describe("validate_config", function() {
|
|
|
828
828
|
|
|
829
829
|
it("should accept an array containing an object with multiple string values", function() {
|
|
830
830
|
const blah = { name: "Blah", property: "blah", type: "string" };
|
|
831
|
-
expectSuccess(settingPlus({ show_if: [
|
|
831
|
+
expectSuccess(settingPlus({ show_if: [{ "bar": "xxx", "blah": "xxx" }] }, undefined, [blah]));
|
|
832
832
|
});
|
|
833
833
|
|
|
834
834
|
it("should accept an array containing an object with multiple array values", function() {
|
|
835
835
|
const blah = { name: "Blah", property: "blah", type: "string" };
|
|
836
|
-
expectSuccess(settingPlus({ show_if: [
|
|
836
|
+
expectSuccess(settingPlus({ show_if: [{ "bar": ["xxx"], "blah": ["xxx"] }] }, undefined, [blah]));
|
|
837
837
|
});
|
|
838
838
|
|
|
839
839
|
it("should reject an array containing any objects with empty array values", function() {
|
|
840
840
|
const blah = { name: "Blah", property: "blah", type: "string" };
|
|
841
|
-
expectFailure(settingPlus({ show_if: [
|
|
841
|
+
expectFailure(settingPlus({ show_if: [{ "bar": [], "blah": "xxx" }] }, undefined, [blah]),
|
|
842
842
|
"template.yml setting “foo” “show_if” property: condition for bar is empty");
|
|
843
843
|
});
|
|
844
844
|
|
|
845
845
|
it("should reject an array containing any objects referring to non-existent settings", function() {
|
|
846
|
-
expectFailure(settingPlus({ show_if: [
|
|
846
|
+
expectFailure(settingPlus({ show_if: [{ "bar": "xxx", "baz": "xxx" }] }),
|
|
847
847
|
"template.yml: “show_if” or “hide_if” property refers to non-existent setting “baz”");
|
|
848
848
|
});
|
|
849
849
|
|
|
850
850
|
it("should accept an array containing an object with a string value and a valid data binding", function() {
|
|
851
|
-
expectSuccess(settingPlus({ show_if: [
|
|
851
|
+
expectSuccess(settingPlus({ show_if: [{ "bar": "xxx", "data.dataset.key": true }] }, { data: [binding] }));
|
|
852
852
|
});
|
|
853
853
|
|
|
854
854
|
it("should reject an array with a data reference when there are no data bindings", function() {
|
|
855
|
-
expectFailure(settingPlus({ show_if: [
|
|
855
|
+
expectFailure(settingPlus({ show_if: [{ "bar": "xxx", "data.dataset.key": true }] }),
|
|
856
856
|
"template.yml: “show_if” or “hide_if” property refers to data binding “data.dataset.key” when none are defined");
|
|
857
857
|
});
|
|
858
858
|
|
|
859
859
|
it("should reject an array with a reference to a non-existent data binding", function() {
|
|
860
|
-
expectFailure(settingPlus({ show_if: [
|
|
860
|
+
expectFailure(settingPlus({ show_if: [{ "bar": "xxx", "data.dataset.nosuchkey": true }] }, { data: [binding] }),
|
|
861
861
|
"template.yml: “show_if” or “hide_if” property refers to non-existent data binding “data.dataset.nosuchkey”");
|
|
862
862
|
});
|
|
863
863
|
|
|
864
864
|
it("should accept an array containing multiple objects of including string and boolean values", function() {
|
|
865
865
|
const blah = { name: "Blah", property: "blah", type: "string" };
|
|
866
866
|
const bool = { name: "Bool", property: "bool", type: "boolean" };
|
|
867
|
-
expectSuccess(settingPlus({ show_if: [
|
|
867
|
+
expectSuccess(settingPlus({ show_if: [{ "bar": "xxx", "blah": "xxx" }, { "bool": true }] }, undefined, [blah, bool]));
|
|
868
868
|
});
|
|
869
869
|
|
|
870
870
|
it("should forbid empty objects", function() {
|
|
@@ -887,26 +887,26 @@ describe("validate_config", function() {
|
|
|
887
887
|
"template.yml: “show_if” or “hide_if” property refers to non-existent setting “baz”");
|
|
888
888
|
});
|
|
889
889
|
it("should accept a reference to a data binding", function() {
|
|
890
|
-
expectSuccess(settingPlus({ show_if: "data.dataset.key" }, { data: [
|
|
890
|
+
expectSuccess(settingPlus({ show_if: "data.dataset.key" }, { data: [binding] }));
|
|
891
891
|
});
|
|
892
892
|
it("should reject a data reference when there are no data bindings", function() {
|
|
893
893
|
expectFailure(settingPlus({ show_if: "data.dataset.key" }),
|
|
894
894
|
"template.yml: “show_if” or “hide_if” property refers to data binding “data.dataset.key” when none are defined");
|
|
895
895
|
});
|
|
896
896
|
it("should reject a reference to a non-existent data binding", function() {
|
|
897
|
-
expectFailure(settingPlus({ show_if: "data.dataset.nosuchkey" }, { data: [
|
|
897
|
+
expectFailure(settingPlus({ show_if: "data.dataset.nosuchkey" }, { data: [binding] }),
|
|
898
898
|
"template.yml: “show_if” or “hide_if” property refers to non-existent data binding “data.dataset.nosuchkey”");
|
|
899
899
|
});
|
|
900
900
|
|
|
901
901
|
// This test is skipped because it doesn’t pass, and looks like it would be
|
|
902
902
|
// complicated to fix.
|
|
903
903
|
it.skip("should reject a string value when referencing a data binding", function() {
|
|
904
|
-
expectFailure(settingPlus({ show_if: { "data.dataset.key": "foo" } }, { data: [
|
|
904
|
+
expectFailure(settingPlus({ show_if: { "data.dataset.key": "foo" } }, { data: [binding] }));
|
|
905
905
|
});
|
|
906
906
|
|
|
907
907
|
it("should reject a reference to a data binding that has no key", function() {
|
|
908
908
|
const binding_undef_key = { name: "No-key binding", dataset: "dataset", key: undefined, type: "column", column: "Foo::A" };
|
|
909
|
-
expectFailure(settingPlus({ show_if: "data.dataset" }, { data: [
|
|
909
|
+
expectFailure(settingPlus({ show_if: "data.dataset" }, { data: [binding_undef_key] }),
|
|
910
910
|
"template.yml: “show_if” or “hide_if” property specifies invalid data binding or column type “data.dataset”");
|
|
911
911
|
});
|
|
912
912
|
it("should accept settings whose names start with /data./ [kiln/flourish-sdk#45]", function() {
|
package/server/columns.js
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
/* * * * * * GENERATED FILE - DO NOT EDIT * * * * * *
|
|
2
|
-
* * * * * * GENERATED FILE - DO NOT EDIT * * * * * *
|
|
3
|
-
* * * * * * GENERATED FILE - DO NOT EDIT * * * * * */
|
|
4
|
-
|
|
5
|
-
'use strict';
|
|
6
|
-
|
|
7
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
8
|
-
|
|
9
|
-
const MAX_INTEGER = Math.pow(2, 31) - 1;
|
|
10
|
-
const MAX_RANGE_LENGTH = Math.pow(2, 15);
|
|
11
|
-
|
|
12
|
-
// Attempt to parse col_spec as a columns spec;
|
|
13
|
-
// return true if we succeed, and false if not.
|
|
14
|
-
function looksLikeMultipleColumns(col_spec) {
|
|
15
|
-
try {
|
|
16
|
-
parseColumns(col_spec);
|
|
17
|
-
}
|
|
18
|
-
catch (e) {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
return true;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function parseColumn(col_spec, is_optional) {
|
|
25
|
-
col_spec = col_spec.toUpperCase();
|
|
26
|
-
if (!/^[A-Z]+$/.test(col_spec)) {
|
|
27
|
-
if (!col_spec) {
|
|
28
|
-
if (is_optional) return -1; // Use -1 for unassigned optional binding
|
|
29
|
-
else throw new Error("Non-optional data binding must specify column");
|
|
30
|
-
}
|
|
31
|
-
if (looksLikeMultipleColumns(col_spec)) {
|
|
32
|
-
throw new Error("You can only select one column");
|
|
33
|
-
}
|
|
34
|
-
else throw new Error("Invalid column specification: " + col_spec);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
var col_ix = 0;
|
|
38
|
-
for (var i = 0; i < col_spec.length; i++) {
|
|
39
|
-
col_ix = col_ix * 26 + (col_spec.charCodeAt(i) - 64);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (col_ix - 1 > MAX_INTEGER) console.warn("Column index out of range");
|
|
43
|
-
return Math.min(col_ix - 1, MAX_INTEGER);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function printColumn(col_ix) {
|
|
47
|
-
col_ix += 1;
|
|
48
|
-
var col_spec = "";
|
|
49
|
-
while (col_ix > 0) {
|
|
50
|
-
var q = Math.floor(col_ix / 26),
|
|
51
|
-
r = col_ix % 26;
|
|
52
|
-
|
|
53
|
-
if (r == 0) {
|
|
54
|
-
q -= 1;
|
|
55
|
-
r += 26;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
col_spec = String.fromCharCode(64 + r) + col_spec;
|
|
59
|
-
col_ix = q;
|
|
60
|
-
}
|
|
61
|
-
return col_spec;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function parseRange(col_range) {
|
|
65
|
-
var dash_mo = col_range.match(/\s*(?:[-–—:]|\.\.)\s*/);
|
|
66
|
-
if (!dash_mo) throw new Error("Failed to parse column range: " + col_range);
|
|
67
|
-
|
|
68
|
-
var first = col_range.substr(0, dash_mo.index),
|
|
69
|
-
last = col_range.substr(dash_mo.index + dash_mo[0].length);
|
|
70
|
-
|
|
71
|
-
var first_ix = parseColumn(first),
|
|
72
|
-
last_ix = parseColumn(last);
|
|
73
|
-
|
|
74
|
-
var r = [];
|
|
75
|
-
var incrementer = last_ix >= first_ix ? 1 : -1;
|
|
76
|
-
var n = Math.abs(last_ix - first_ix) + 1;
|
|
77
|
-
|
|
78
|
-
if (n > MAX_RANGE_LENGTH) {
|
|
79
|
-
console.warn("Truncating excessively long range");
|
|
80
|
-
n = MAX_RANGE_LENGTH;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
for (var i = 0; i < n; i++) {
|
|
84
|
-
r.push(first_ix + i*incrementer);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return r;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function printRange(start, end) {
|
|
91
|
-
return printColumn(start) + "-" + printColumn(end);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function parseColumns(cols_spec) {
|
|
95
|
-
var indexes = [];
|
|
96
|
-
|
|
97
|
-
cols_spec = cols_spec.replace(/^\s+|\s+$/g, "");
|
|
98
|
-
var split_cols = cols_spec.split(/\s*,\s*/);
|
|
99
|
-
if (split_cols.length == 1 && split_cols[0] === "") split_cols = [];
|
|
100
|
-
|
|
101
|
-
for (var i = 0; i < split_cols.length; i++) {
|
|
102
|
-
var col_or_range = split_cols[i];
|
|
103
|
-
if (/^[A-Za-z]+$/.test(col_or_range)) {
|
|
104
|
-
indexes.push(parseColumn(col_or_range));
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
Array.prototype.push.apply(indexes, parseRange(col_or_range));
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return indexes;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function splitIntoRanges(indexes) {
|
|
115
|
-
if (!indexes.length) {
|
|
116
|
-
return [];
|
|
117
|
-
}
|
|
118
|
-
var ranges = [];
|
|
119
|
-
var start = indexes[0], end = indexes[0];
|
|
120
|
-
var direction = null;
|
|
121
|
-
for (var i = 0; i < indexes.length - 1; i++) {
|
|
122
|
-
var diff = indexes[i + 1] - indexes[i];
|
|
123
|
-
if (direction === null && Math.abs(diff) === 1) {
|
|
124
|
-
// It's a range with either ascending columns (direction=1), or descending
|
|
125
|
-
// columns (direction=-1)
|
|
126
|
-
end = indexes[i + 1];
|
|
127
|
-
direction = diff;
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (diff === direction) {
|
|
132
|
-
// The range is continuing in the same direction as before
|
|
133
|
-
end = indexes[i + 1];
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// There's nothing more in the range, so add it, and start a new range from the
|
|
138
|
-
// next column
|
|
139
|
-
ranges.push([start, end]);
|
|
140
|
-
start = end = indexes[i + 1];
|
|
141
|
-
direction = null;
|
|
142
|
-
}
|
|
143
|
-
// There will always be a range which hasn't been added at the end
|
|
144
|
-
ranges.push([start, end]);
|
|
145
|
-
return ranges;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function printColumns(indexes) {
|
|
149
|
-
var ranges = splitIntoRanges(indexes);
|
|
150
|
-
|
|
151
|
-
var r = [];
|
|
152
|
-
for (var i = 0; i < ranges.length; i++) {
|
|
153
|
-
var range = ranges[i];
|
|
154
|
-
if (range[0] == range[1]) r.push(printColumn(range[0]));
|
|
155
|
-
else r.push(printRange(range[0], range[1]));
|
|
156
|
-
}
|
|
157
|
-
return r.join(",");
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function parseDataBinding(d, data_table_ids) {
|
|
161
|
-
var r = {};
|
|
162
|
-
|
|
163
|
-
if (!(d.type in d)) {
|
|
164
|
-
if (d.optional) return r;
|
|
165
|
-
throw new Error("Data binding must specify '" + d.type + "': " + JSON.stringify(d));
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
var double_colon_ix = d[d.type].indexOf("::");
|
|
169
|
-
if (double_colon_ix == -1) throw new Error("Invalid data binding: " + d[d.type]);
|
|
170
|
-
var data_table_name = d[d.type].substr(0, double_colon_ix);
|
|
171
|
-
r.data_table_id = data_table_ids[data_table_name];
|
|
172
|
-
|
|
173
|
-
var col_spec = d[d.type].substr(double_colon_ix + 2);
|
|
174
|
-
if (d.type == "column") r.column = parseColumn(col_spec, d.optional);
|
|
175
|
-
else if (d.type == "columns") r.columns = parseColumns(col_spec);
|
|
176
|
-
else throw new Error("Unknown data binding type: " + d.type);
|
|
177
|
-
|
|
178
|
-
return r;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function printDataBinding(r, data_table_names, print_data_table_name, optional) {
|
|
182
|
-
var data_table_name = print_data_table_name ? data_table_names[r.data_table_id] + "::" : "";
|
|
183
|
-
if ("column" in r) {
|
|
184
|
-
return data_table_name + printColumn(r.column);
|
|
185
|
-
}
|
|
186
|
-
else if ("columns" in r) {
|
|
187
|
-
return data_table_name + printColumns(r.columns);
|
|
188
|
-
}
|
|
189
|
-
else if (optional) {
|
|
190
|
-
return "";
|
|
191
|
-
}
|
|
192
|
-
throw new Error("Data binding must have .column or .columns");
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
exports.parseColumn = parseColumn;
|
|
196
|
-
exports.parseColumns = parseColumns;
|
|
197
|
-
exports.parseDataBinding = parseDataBinding;
|
|
198
|
-
exports.parseRange = parseRange;
|
|
199
|
-
exports.printColumn = printColumn;
|
|
200
|
-
exports.printColumns = printColumns;
|
|
201
|
-
exports.printDataBinding = printDataBinding;
|