@flourish/sdk 5.0.0 → 5.2.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.
Files changed (103) hide show
  1. package/RELEASE_NOTES.md +8 -0
  2. package/bin/flourish.js +6 -6
  3. package/common/embed/credit.js +5 -5
  4. package/common/embed/customer_analytics.js +20 -17
  5. package/common/embed/embedding.js +71 -38
  6. package/common/embed/localizations.d.ts +8 -8
  7. package/common/embed/localizations.js +4 -4
  8. package/common/embed/parse_query_params.js +2 -1
  9. package/common/package.json +11 -1
  10. package/common/tsconfig.sdk.tsbuildinfo +1 -1
  11. package/common/utils/columns.js +34 -22
  12. package/common/utils/data.d.ts +36 -15
  13. package/common/utils/data.js +136 -51
  14. package/common/utils/json.d.ts +6 -3
  15. package/common/utils/json.js +12 -9
  16. package/common/utils/polyfills.js +1 -1
  17. package/common/utils/state.d.ts +2 -2
  18. package/common/utils/state.js +43 -27
  19. package/common/utils/types.d.ts +63 -0
  20. package/common/utils/types.js +3 -0
  21. package/lib/cmd/assign-version-number.js +5 -5
  22. package/lib/cmd/build.js +1 -1
  23. package/lib/cmd/delete.js +2 -2
  24. package/lib/cmd/history.js +4 -2
  25. package/lib/cmd/list.js +13 -11
  26. package/lib/cmd/login.js +1 -1
  27. package/lib/cmd/logout.js +17 -5
  28. package/lib/cmd/publish.js +13 -13
  29. package/lib/cmd/register.js +3 -3
  30. package/lib/cmd/run.js +3 -3
  31. package/lib/cmd/upgrade/1-convert-config-to-yaml.js +14 -14
  32. package/lib/cmd/upgrade/2-convert-index-html.js +4 -4
  33. package/lib/cmd/upgrade/3-add-build-config.js +5 -5
  34. package/lib/cmd/upgrade/4-remove-autoheight-config.js +3 -3
  35. package/lib/cmd/upgrade/index.js +6 -6
  36. package/lib/common.js +11 -7
  37. package/lib/log.js +7 -7
  38. package/lib/sdk.js +86 -38
  39. package/lib/validate_config.js +30 -30
  40. package/package.json +5 -3
  41. package/rollup.config.mjs +20 -0
  42. package/server/columns.js +201 -0
  43. package/server/comms_js.js +3 -3
  44. package/server/data.js +327 -0
  45. package/server/index.js +62 -44
  46. package/server/index_html.js +16 -9
  47. package/server/json.js +66 -0
  48. package/server/views/index.html +3 -3
  49. package/site/embedded.js +1 -1
  50. package/site/favicon.ico +0 -0
  51. package/site/fonts/canva-sans/WOFF/CanvaSans-Bold.woff +0 -0
  52. package/site/fonts/canva-sans/WOFF/CanvaSans-Bold.woff2 +0 -0
  53. package/site/fonts/canva-sans/WOFF/CanvaSans-Regular.woff +0 -0
  54. package/site/fonts/canva-sans/WOFF/CanvaSans-Regular.woff2 +0 -0
  55. package/site/fonts/canva-sans/WOFF/CanvaSansDisplay-Bold.woff +0 -0
  56. package/site/fonts/canva-sans/WOFF/CanvaSansDisplay-Bold.woff2 +0 -0
  57. package/site/fonts/canva-sans/WOFF/CanvaSansDisplay-Regular.woff +0 -0
  58. package/site/fonts/canva-sans/WOFF/CanvaSansDisplay-Regular.woff2 +0 -0
  59. package/site/fonts/canva-sans-variable/TTF/CanvaSans-VF.ttf +0 -0
  60. package/site/fonts/canva-sans-variable/TTF/CanvaSansDisplay-VF.ttf +0 -0
  61. package/site/fonts/canva-sans-variable/WOFF/CanvaSans-VF.woff +0 -0
  62. package/site/fonts/canva-sans-variable/WOFF/CanvaSansDisplay-VF.woff +0 -0
  63. package/site/fonts/canva-sans.css +53 -0
  64. package/site/images/bosh-white.svg +12 -0
  65. package/site/images/bosh.svg +10 -6
  66. package/site/images/flourish_logo.svg +20 -0
  67. package/site/images/flourish_logo_white.svg +20 -0
  68. package/site/images/icon-chart-bar.svg +3 -0
  69. package/site/images/icon-chart-line.svg +3 -0
  70. package/site/images/icon-chart-pie.svg +3 -0
  71. package/site/images/icon-chevron-down-small-white.svg +3 -0
  72. package/site/images/icon-editable.svg +1 -8
  73. package/site/images/icon-gift.svg +3 -0
  74. package/site/images/icon-grid-view-white.svg +3 -0
  75. package/site/images/icon-grid-view.svg +3 -0
  76. package/site/images/icon-presentation.svg +2 -2
  77. package/site/images/icon-presenter.svg +3 -0
  78. package/site/images/icon-private.svg +1 -1
  79. package/site/images/icon-star.svg +3 -0
  80. package/site/images/icon-table-border-all.svg +3 -0
  81. package/site/images/icon-table-white.svg +3 -0
  82. package/site/images/icon-table.svg +3 -0
  83. package/site/images/icon-upload-black.svg +3 -0
  84. package/site/images/icon-upload-cloud.svg +3 -0
  85. package/site/images/icon-upload.svg +2 -2
  86. package/site/images/icon-viewable.svg +1 -1
  87. package/site/images/instagram-logo.svg +1 -0
  88. package/site/images/linkedin-logo.svg +1 -0
  89. package/site/images/logo.png +0 -0
  90. package/site/images/logo.svg +20 -1
  91. package/site/images/made_with_flourish.svg +38 -4
  92. package/site/images/share_image.jpg +0 -0
  93. package/site/images/slide_visualisation.png +0 -0
  94. package/site/images/spinner_data.json +1 -0
  95. package/site/images/x-logo.svg +1 -0
  96. package/site/images/youtube-logo.svg +1 -0
  97. package/site/script.js +3 -3
  98. package/site/sdk.css +2 -2
  99. package/site/talk_to_server.js +6 -4
  100. package/test/lib/sdk.js +13 -13
  101. package/test/lib/validate_config.js +61 -61
  102. package/tsconfig.json +1 -1
  103. package/site/images/logo_white.png +0 -0
package/RELEASE_NOTES.md CHANGED
@@ -1,3 +1,11 @@
1
+ # 5.2.0
2
+ * Fixes issue publishing templates with complex settings
3
+ * Improves html sanitation in template publishing workflow
4
+
5
+ # 5.1.0
6
+ * Revoke SDK token on logout
7
+ this improves on the previous behaviour where logging out would only purge tokens locally.
8
+
1
9
  # 5.0.0
2
10
  * Add automatic SDK local settings restore on template reload
3
11
  * Upgrade node-fetch dependency to avoid annoying deprecation warning. #91
package/bin/flourish.js CHANGED
@@ -11,7 +11,7 @@ const OPTS = {
11
11
  "help", "build", "open", "debug", "full", "force",
12
12
 
13
13
  // Options for 'publish'
14
- "prerelease", "patch", "release", "local-testing"
14
+ "prerelease", "patch", "release", "local-testing",
15
15
  ],
16
16
  string: [
17
17
  "host", "listen", "port", "user", "password",
@@ -35,7 +35,7 @@ const OPTS = {
35
35
  build: true,
36
36
  open: false,
37
37
 
38
- env: "development"
38
+ env: "development",
39
39
  },
40
40
 
41
41
  alias: {
@@ -48,7 +48,7 @@ const OPTS = {
48
48
  if (unknown_option.startsWith("-")) {
49
49
  log.die("Unknown option: " + unknown_option);
50
50
  }
51
- }
51
+ },
52
52
  };
53
53
 
54
54
  // Unhandled rejections indicate an error in the app
@@ -73,7 +73,7 @@ const COMMANDS = [
73
73
  "delete",
74
74
  "upgrade",
75
75
  "list",
76
- "history"
76
+ "history",
77
77
  ];
78
78
 
79
79
  function main() {
@@ -88,8 +88,8 @@ function main() {
88
88
  args._ = args._.map(String);
89
89
 
90
90
  let [command] = args._;
91
- if (args.version) command = "version";
92
- else if (args.help) command = "help";
91
+ if (args.version) { command = "version"; }
92
+ else if (args.help) { command = "help"; }
93
93
 
94
94
  if (!command) {
95
95
  return log.die("No command specified. Type ‘flourish help’ for help.");
@@ -3,7 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getLocalizedCreditTextAndUrl = exports.createFlourishCredit = void 0;
6
+ exports.createFlourishCredit = createFlourishCredit;
7
+ exports.getLocalizedCreditTextAndUrl = getLocalizedCreditTextAndUrl;
7
8
  const localizations_1 = __importDefault(require("./localizations"));
8
9
  function createFlourishCredit(credit_url, query_string, public_url, credit_text) {
9
10
  credit_url = credit_url || "https://flourish.studio",
@@ -29,19 +30,18 @@ function createFlourishCredit(credit_url, query_string, public_url, credit_text)
29
30
  a.appendChild(span);
30
31
  return credit;
31
32
  }
32
- exports.createFlourishCredit = createFlourishCredit;
33
33
  function getLocalizedCreditTextAndUrl(lang, credit_key) {
34
34
  var credit_text, credit_url;
35
35
  lang = lang || "en", credit_key = credit_key || "";
36
36
  credit_text = localizations_1.default[lang].credits[credit_key] || localizations_1.default.en.credits[credit_key] || localizations_1.default.en.credits.default;
37
37
  if (typeof credit_text == "object") {
38
- if (credit_text.url)
38
+ if (credit_text.url) {
39
39
  credit_url = credit_text.url;
40
+ }
40
41
  credit_text = credit_text.text;
41
42
  }
42
43
  return {
43
44
  credit_text: credit_text,
44
- credit_url: credit_url
45
+ credit_url: credit_url,
45
46
  };
46
47
  }
47
- exports.getLocalizedCreditTextAndUrl = getLocalizedCreditTextAndUrl;
@@ -1,6 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initCustomerAnalytics = exports.dispatchAnalyticsEvent = exports.removeAnalyticsListener = exports.addAnalyticsListener = exports.sendCustomerAnalyticsMessage = void 0;
3
+ exports.sendCustomerAnalyticsMessage = sendCustomerAnalyticsMessage;
4
+ exports.addAnalyticsListener = addAnalyticsListener;
5
+ exports.removeAnalyticsListener = removeAnalyticsListener;
6
+ exports.dispatchAnalyticsEvent = dispatchAnalyticsEvent;
7
+ exports.initCustomerAnalytics = initCustomerAnalytics;
4
8
  // Embedded code - must work in IE
5
9
  var enabled = false;
6
10
  function getLocationData() {
@@ -28,17 +32,20 @@ function getLocationData() {
28
32
  return data;
29
33
  }
30
34
  function sendCustomerAnalyticsMessage(message) {
31
- if (!enabled)
35
+ if (!enabled) {
32
36
  return;
33
- if (window.top === window.self)
37
+ }
38
+ if (window.top === window.self) {
34
39
  return;
40
+ }
35
41
  var embedded_window = window;
36
- if (embedded_window.location.pathname === "srcdoc")
42
+ if (embedded_window.location.pathname === "srcdoc") {
37
43
  embedded_window = embedded_window.parent;
44
+ }
38
45
  var location_data = getLocationData();
39
46
  var message_with_metadata = {
40
47
  sender: "Flourish",
41
- method: "customerAnalytics"
48
+ method: "customerAnalytics",
42
49
  };
43
50
  for (var key in location_data) {
44
51
  if (location_data.hasOwnProperty(key)) {
@@ -52,14 +59,12 @@ function sendCustomerAnalyticsMessage(message) {
52
59
  }
53
60
  embedded_window.parent.postMessage(JSON.stringify(message_with_metadata), "*");
54
61
  }
55
- exports.sendCustomerAnalyticsMessage = sendCustomerAnalyticsMessage;
56
62
  function addAnalyticsListener(callback) {
57
63
  if (typeof callback !== "function") {
58
64
  throw new Error("Analytics callback is not a function");
59
65
  }
60
66
  window.Flourish._analytics_listeners.push(callback);
61
67
  }
62
- exports.addAnalyticsListener = addAnalyticsListener;
63
68
  function removeAnalyticsListener(callback) {
64
69
  if (typeof callback !== "function") {
65
70
  throw new Error("Analytics callback is not a function");
@@ -68,47 +73,45 @@ function removeAnalyticsListener(callback) {
68
73
  return callback !== listener;
69
74
  });
70
75
  }
71
- exports.removeAnalyticsListener = removeAnalyticsListener;
72
76
  function dispatchAnalyticsEvent(message) {
73
77
  // If the window.Flourish object hasn't been created by the customer, they
74
78
  // can't be listening for analytics events
75
- if (!window.Flourish)
79
+ if (!window.Flourish) {
76
80
  return;
81
+ }
77
82
  window.Flourish._analytics_listeners.forEach(function (listener) {
78
83
  listener(message);
79
84
  });
80
85
  }
81
- exports.dispatchAnalyticsEvent = dispatchAnalyticsEvent;
82
86
  function initCustomerAnalytics() {
83
87
  enabled = true;
84
88
  var events = [
85
89
  {
86
90
  event_name: "click",
87
91
  action_name: "click",
88
- use_capture: true
92
+ use_capture: true,
89
93
  },
90
94
  {
91
95
  event_name: "keydown",
92
96
  action_name: "key_down",
93
- use_capture: true
97
+ use_capture: true,
94
98
  },
95
99
  {
96
100
  event_name: "mouseenter",
97
101
  action_name: "mouse_enter",
98
- use_capture: false
102
+ use_capture: false,
99
103
  },
100
104
  {
101
105
  event_name: "mouseleave",
102
106
  action_name: "mouse_leave",
103
- use_capture: false
104
- }
107
+ use_capture: false,
108
+ },
105
109
  ];
106
110
  events.forEach(function (event) {
107
111
  document.body.addEventListener(event.event_name, function () {
108
112
  sendCustomerAnalyticsMessage({
109
- action: event.action_name
113
+ action: event.action_name,
110
114
  });
111
115
  }, event.use_capture);
112
116
  });
113
117
  }
114
- exports.initCustomerAnalytics = initCustomerAnalytics;
@@ -14,42 +14,51 @@ function isFixedHeight() {
14
14
  var params = (0, parse_query_params_1.default)();
15
15
  // "referrer" in params implies this is an Embedly embed
16
16
  // Check whether embedding site is known to support dynamic resizing
17
- if ("referrer" in params)
17
+ if ("referrer" in params) {
18
18
  is_fixed_height = /^https:\/\/medium.com\//.test(params.referrer);
19
- else
19
+ }
20
+ else {
20
21
  is_fixed_height = !("auto" in params);
22
+ }
21
23
  }
22
24
  return is_fixed_height;
23
25
  }
24
26
  function getHeightForBreakpoint(width) {
25
27
  var breakpoint_width = width || window.innerWidth;
26
- if (breakpoint_width > 999)
28
+ if (breakpoint_width > 999) {
27
29
  return 650;
28
- if (breakpoint_width > 599)
30
+ }
31
+ if (breakpoint_width > 599) {
29
32
  return 575;
33
+ }
30
34
  return 400;
31
35
  }
32
36
  function initScrolly(opts) {
33
- if (!opts)
37
+ if (!opts) {
34
38
  return;
35
- if (window.top === window.self)
39
+ }
40
+ if (window.top === window.self) {
36
41
  return;
42
+ }
37
43
  var embedded_window = window;
38
- if (embedded_window.location.pathname == "srcdoc")
44
+ if (embedded_window.location.pathname == "srcdoc") {
39
45
  embedded_window = embedded_window.parent;
46
+ }
40
47
  var message = {
41
48
  sender: "Flourish",
42
49
  method: "scrolly",
43
- captions: opts.captions
50
+ captions: opts.captions,
44
51
  };
45
52
  embedded_window.parent.postMessage(JSON.stringify(message), "*");
46
53
  }
47
54
  function notifyParentWindow(height, opts) {
48
- if (window.top === window.self)
55
+ if (window.top === window.self) {
49
56
  return;
57
+ }
50
58
  var embedded_window = window;
51
- if (embedded_window.location.pathname == "srcdoc")
59
+ if (embedded_window.location.pathname == "srcdoc") {
52
60
  embedded_window = embedded_window.parent;
61
+ }
53
62
  if (is_amp) {
54
63
  // Message is not stringified for AMP
55
64
  height = parseInt(height, 10);
@@ -63,13 +72,14 @@ function notifyParentWindow(height, opts) {
63
72
  var message = {
64
73
  sender: "Flourish",
65
74
  context: "iframe.resize",
66
- method: "resize",
75
+ method: "resize", // backwards compatibility
67
76
  height: height,
68
77
  src: embedded_window.location.toString(),
69
78
  };
70
79
  if (opts) {
71
- for (var name in opts)
80
+ for (var name in opts) {
72
81
  message[name] = opts[name];
82
+ }
73
83
  }
74
84
  embedded_window.parent.postMessage(JSON.stringify(message), "*");
75
85
  }
@@ -100,10 +110,12 @@ function validateWarnMessage(message) {
100
110
  console.warn("BUG: validateWarnMessage called for method" + message.method);
101
111
  return false;
102
112
  }
103
- if ((message.message != null) && !isString(message.message))
113
+ if ((message.message != null) && !isString(message.message)) {
104
114
  return false;
105
- if ((message.explanation != null) && !isString(message.explanation))
115
+ }
116
+ if ((message.explanation != null) && !isString(message.explanation)) {
106
117
  return false;
118
+ }
107
119
  return true;
108
120
  }
109
121
  function validateResizeMessage(message) {
@@ -111,12 +123,15 @@ function validateResizeMessage(message) {
111
123
  console.warn("BUG: validateResizeMessage called for method" + message.method);
112
124
  return false;
113
125
  }
114
- if (!isString(message.src))
126
+ if (!isString(message.src)) {
115
127
  return false;
116
- if (!isString(message.context))
128
+ }
129
+ if (!isString(message.context)) {
117
130
  return false;
118
- if (!isPossibleHeight(message.height))
131
+ }
132
+ if (!isPossibleHeight(message.height)) {
119
133
  return false;
134
+ }
120
135
  return true;
121
136
  }
122
137
  function validateSetSettingMessage(_message) {
@@ -127,8 +142,9 @@ function validateScrolly(message) {
127
142
  console.warn("BUG: validateScrolly called for method" + message.method);
128
143
  return false;
129
144
  }
130
- if (!Array.isArray(message.captions))
145
+ if (!Array.isArray(message.captions)) {
131
146
  return false;
147
+ }
132
148
  return true;
133
149
  }
134
150
  function validateCustomerAnalyticsMessage(message) {
@@ -148,10 +164,12 @@ function validateRequestUpload(message) {
148
164
  }
149
165
  // FIXME: when adding validation for setSetting (see above) we should
150
166
  // also validate that this is a valid setting name of appropriate type
151
- if (!isString(message.name))
167
+ if (!isString(message.name)) {
152
168
  return false;
153
- if (!(message.accept == null || isString(message.accept)))
169
+ }
170
+ if (!(message.accept == null || isString(message.accept))) {
154
171
  return false;
172
+ }
155
173
  return true;
156
174
  }
157
175
  function getMessageValidators(methods) {
@@ -161,7 +179,7 @@ function getMessageValidators(methods) {
161
179
  "setSetting": validateSetSettingMessage,
162
180
  "customerAnalytics": validateCustomerAnalyticsMessage,
163
181
  "request-upload": validateRequestUpload,
164
- "scrolly": validateScrolly
182
+ "scrolly": validateScrolly,
165
183
  };
166
184
  var validators = {};
167
185
  for (var i = 0; i < methods.length; i++) {
@@ -187,11 +205,13 @@ function startEventListeners(callback, allowed_methods, embed_domain) {
187
205
  const origin = event.origin.toLowerCase();
188
206
  embed_domain = embed_domain.toLowerCase();
189
207
  // Allow the domain itself…
190
- if (origin.endsWith("//" + embed_domain))
208
+ if (origin.endsWith("//" + embed_domain)) {
191
209
  return true;
210
+ }
192
211
  // and subdomains
193
- if (origin.endsWith("." + embed_domain))
212
+ if (origin.endsWith("." + embed_domain)) {
194
213
  return true;
214
+ }
195
215
  }
196
216
  if (event.origin.match(/\/\/localhost:\d+$|\/\/(?:public|app)\.flourish.devlocal$|\/\/flourish-api\.com$|\.flourish\.(?:local(:\d+)?|net|rocks|studio)$|\.uri\.sh$|\/\/flourish-user-templates\.com$/)) {
197
217
  return true;
@@ -200,10 +220,12 @@ function startEventListeners(callback, allowed_methods, embed_domain) {
200
220
  })();
201
221
  // event.source is null when the message is sent by an extension
202
222
  // https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Using_window.postMessage_in_extensions
203
- if (event.source == null)
223
+ if (event.source == null) {
204
224
  return;
205
- if (!is_accepted_event_origin)
225
+ }
226
+ if (!is_accepted_event_origin) {
206
227
  return;
228
+ }
207
229
  var message;
208
230
  try {
209
231
  message = typeof event.data === "object" ? event.data : JSON.parse(event.data);
@@ -212,8 +234,9 @@ function startEventListeners(callback, allowed_methods, embed_domain) {
212
234
  console.warn("Unexpected non-JSON message: " + JSON.stringify(event.data));
213
235
  return;
214
236
  }
215
- if (message.sender !== "Flourish")
237
+ if (message.sender !== "Flourish") {
216
238
  return;
239
+ }
217
240
  if (!message.method) {
218
241
  console.warn("The 'method' property was missing from message", message);
219
242
  return;
@@ -245,13 +268,15 @@ function onSafariWindowResize() {
245
268
  var containers = document.querySelectorAll(".flourish-embed");
246
269
  for (var i = 0; i < containers.length; i++) {
247
270
  var container = containers[i];
248
- if (container.getAttribute("data-width"))
271
+ if (container.getAttribute("data-width")) {
249
272
  continue;
273
+ }
250
274
  var iframe = container.querySelector("iframe");
251
275
  // When embeds are dynamically loaded, we might have a container without a
252
276
  // loaded iframe yet
253
- if (!iframe)
277
+ if (!iframe) {
254
278
  continue;
279
+ }
255
280
  var computed_style = window.getComputedStyle(container);
256
281
  var width = container.offsetWidth - parseFloat(computed_style.paddingLeft) - parseFloat(computed_style.paddingRight);
257
282
  iframe.style.width = width + "px";
@@ -295,7 +320,8 @@ function createScrolly(iframe, captions) {
295
320
  step.style.marginLeft = "auto";
296
321
  step.style.marginRight = "auto";
297
322
  var caption = document.createElement("div");
298
- caption.innerHTML = dompurify_1.default.sanitize(d);
323
+ // eslint-disable-next-line flourish-security/dompurify
324
+ caption.innerHTML = dompurify_1.default.sanitize(d, { ADD_ATTR: ["target"] });
299
325
  caption.style.visibility = has_content ? "" : "hidden";
300
326
  caption.style.display = "inline-block";
301
327
  caption.style.paddingTop = "1.25em";
@@ -320,8 +346,9 @@ function initIntersection(container) {
320
346
  entries.forEach(function (entry) {
321
347
  if (entry.isIntersecting) {
322
348
  var iframe = container.querySelector("iframe");
323
- if (iframe)
349
+ if (iframe) {
324
350
  iframe.src = iframe.src.replace(/#slide-.*/, "") + "#slide-" + entry.target.getAttribute("data-slide");
351
+ }
325
352
  }
326
353
  });
327
354
  }, { rootMargin: "0px 0px -" + t + " 0px" });
@@ -361,7 +388,7 @@ function createEmbedIframe(embed_url, container, width, height, play_on_load) {
361
388
  iframe: iframe,
362
389
  width: width,
363
390
  height: height,
364
- play_on_load: play_on_load
391
+ play_on_load: play_on_load,
365
392
  };
366
393
  // If this is the first embed on the page which is isn't displayed, set up a
367
394
  // list of hidden iframes to poll
@@ -411,22 +438,28 @@ function setIframeContent(embed_url, container, iframe, width, height, play_on_l
411
438
  else if (width && width.match(/^[ \t\r\n\f]*([+-]?\d+|\d*\.\d+(?:[eE][+-]?\d+)?)(?:\\?[Pp]|\\0{0,4}[57]0(?:\r\n|[ \t\r\n\f])?)(?:\\?[Xx]|\\0{0,4}[57]8(?:\r\n|[ \t\r\n\f])?)[ \t\r\n\f]*$/)) {
412
439
  width_in_px = parseFloat(width);
413
440
  }
414
- if (height && typeof height === "number")
441
+ if (height && typeof height === "number") {
415
442
  height = "" + height + "px";
443
+ }
416
444
  // Odd design decision in Safari means need to set fixed width rather than %
417
445
  // as will try and size iframe to content otherwise. Must also set scrolling=no
418
- if (width)
446
+ if (width) {
419
447
  iframe.style.width = width;
420
- else if (isSafari())
448
+ }
449
+ else if (isSafari()) {
421
450
  iframe.style.width = container.offsetWidth + "px";
422
- else
451
+ }
452
+ else {
423
453
  iframe.style.width = "100%";
454
+ }
424
455
  var fixed_height = !!height;
425
456
  if (!fixed_height) {
426
- if (embed_url.match(/\?/))
457
+ if (embed_url.match(/\?/)) {
427
458
  embed_url += "&auto=1";
428
- else
459
+ }
460
+ else {
429
461
  embed_url += "?auto=1";
462
+ }
430
463
  // For initial height, use our standard breakpoints, based on the explicit
431
464
  // pixel width if we know it, or the iframe's measured width if not.
432
465
  height = getHeightForBreakpoint(width_in_px || iframe.offsetWidth) + "px";
@@ -453,7 +486,7 @@ function initEmbedding() {
453
486
  isSafari: isSafari,
454
487
  initCustomerAnalytics: customer_analytics_1.initCustomerAnalytics,
455
488
  addAnalyticsListener: customer_analytics_1.addAnalyticsListener,
456
- sendCustomerAnalyticsMessage: customer_analytics_1.sendCustomerAnalyticsMessage
489
+ sendCustomerAnalyticsMessage: customer_analytics_1.sendCustomerAnalyticsMessage,
457
490
  };
458
491
  }
459
492
  exports.default = initEmbedding;
@@ -1,12 +1,12 @@
1
1
  declare namespace _default {
2
2
  namespace de {
3
3
  namespace credits {
4
- const _default: string;
4
+ let _default: string;
5
5
  export { _default as default };
6
6
  }
7
7
  }
8
8
  namespace en {
9
- const credits_1: {
9
+ let credits_1: {
10
10
  default: {
11
11
  text: string;
12
12
  url: string;
@@ -159,7 +159,7 @@ declare namespace _default {
159
159
  export { credits_1 as credits };
160
160
  }
161
161
  namespace es {
162
- const credits_2: {
162
+ let credits_2: {
163
163
  default: string;
164
164
  bar_race: {
165
165
  text: string;
@@ -173,7 +173,7 @@ declare namespace _default {
173
173
  export { credits_2 as credits };
174
174
  }
175
175
  namespace fr {
176
- const credits_3: {
176
+ let credits_3: {
177
177
  default: string;
178
178
  bar_race: {
179
179
  text: string;
@@ -187,7 +187,7 @@ declare namespace _default {
187
187
  export { credits_3 as credits };
188
188
  }
189
189
  namespace it {
190
- const credits_4: {
190
+ let credits_4: {
191
191
  default: string;
192
192
  bar_race: {
193
193
  text: string;
@@ -201,7 +201,7 @@ declare namespace _default {
201
201
  export { credits_4 as credits };
202
202
  }
203
203
  namespace mi {
204
- const credits_5: {
204
+ let credits_5: {
205
205
  default: string;
206
206
  bar_race: {
207
207
  text: string;
@@ -215,7 +215,7 @@ declare namespace _default {
215
215
  export { credits_5 as credits };
216
216
  }
217
217
  namespace nl {
218
- const credits_6: {
218
+ let credits_6: {
219
219
  default: string;
220
220
  bar_race: {
221
221
  text: string;
@@ -228,7 +228,7 @@ declare namespace _default {
228
228
  };
229
229
  export { credits_6 as credits };
230
230
  }
231
- const pt: {
231
+ let pt: {
232
232
  default: string;
233
233
  bar_race: {
234
234
  text: string;
@@ -45,7 +45,7 @@ exports.default = {
45
45
  "text-annotator": { text: "Interactive content by Flourish", url: "https://flourish.studio/blog/text-annotator-template/" },
46
46
  "tournament": { text: "Interactive content by Flourish", url: "https://flourish.studio/visualisations/tournament-chart/" },
47
47
  "word-cloud": { text: "A Flourish data visualization", url: "https://flourish.studio/blog/online-wordcloud-custom-fonts/" },
48
- }
48
+ },
49
49
  },
50
50
  "es": {
51
51
  credits: {
@@ -66,7 +66,7 @@ exports.default = {
66
66
  "default": "Creato con Flourish",
67
67
  "bar_race": { text: "Creato con Flourish", url: "https://flourish.studio/visualisations/bar-chart-race/" },
68
68
  "bar-chart-race": { text: "Creato con Flourish", url: "https://flourish.studio/visualisations/bar-chart-race/" },
69
- }
69
+ },
70
70
  },
71
71
  "mi": {
72
72
  credits: {
@@ -85,6 +85,6 @@ exports.default = {
85
85
  "pt": {
86
86
  "default": "Feito com Flourish",
87
87
  "bar_race": { text: "Feito com Flourish", url: "https://flourish.studio/visualisations/bar-chart-race/" },
88
- "bar-chart-race": { text: "Feito com Flourish", url: "https://flourish.studio/visualisations/bar-chart-race/" }
89
- }
88
+ "bar-chart-race": { text: "Feito com Flourish", url: "https://flourish.studio/visualisations/bar-chart-race/" },
89
+ },
90
90
  };
@@ -6,8 +6,9 @@ function parseQueryParams() {
6
6
  var location = window.location;
7
7
  // We use srcdoc to load the decrypted content for password-protected projects,
8
8
  // which creates a nested window.
9
- if (location.href == "about:srcdoc")
9
+ if (location.href == "about:srcdoc") {
10
10
  location = window.parent.location;
11
+ }
11
12
  var params = {};
12
13
  (function (query, re, match) {
13
14
  while (match = re.exec(query)) {
@@ -1,9 +1,19 @@
1
1
  {
2
2
  "name": "@flourish/common",
3
3
  "description": "Common shared utilities",
4
+ "scripts": {
5
+ "test": "jest",
6
+ "test:ci": "jest --config jest.config.ci.mjs"
7
+ },
4
8
  "dependencies": {
5
9
  "@adobe/css-tools": "^4.3.3",
6
- "@flourish/interpreter": "^8.4.0",
10
+ "@flourish/interpreter": "^9.1.1",
7
11
  "dompurify": "^3.1.4"
12
+ },
13
+ "devDependencies": {
14
+ "@types/jest": "^29.5.12",
15
+ "jest": "^29.7.0",
16
+ "jest-junit": "^16.0.0",
17
+ "ts-jest": "^29.1.5"
8
18
  }
9
19
  }