UNPKG

13.6 kBJavaScriptView Raw
1function _toArray(arr) { return _arrayWithHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableRest(); }
2
3function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
4
5function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6
7function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
8
9function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
10
11function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
12
13function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
14
15function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
16
17function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
18
19function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
20
21function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
22
23import "core-js/modules/es.array.iterator.js";
24import "core-js/modules/es.object.from-entries.js";
25import "core-js/modules/es.array.filter.js";
26import "core-js/modules/es.object.to-string.js";
27import "core-js/modules/es.object.entries.js";
28import "core-js/modules/es.object.assign.js";
29import "core-js/modules/es.number.is-integer.js";
30import "core-js/modules/es.number.constructor.js";
31import "core-js/modules/es.regexp.exec.js";
32import "core-js/modules/es.string.search.js";
33import "core-js/modules/es.promise.js";
34import "core-js/modules/web.dom-collections.for-each.js";
35import "core-js/modules/es.array.map.js";
36import "core-js/modules/es.array.includes.js";
37import "core-js/modules/es.string.includes.js";
38import "core-js/modules/es.object.values.js";
39import "core-js/modules/es.array.concat.js";
40import "core-js/modules/es.string.iterator.js";
41import "core-js/modules/web.dom-collections.iterator.js";
42import "core-js/modules/web.url.js";
43import "core-js/modules/web.url-search-params.js";
44import "core-js/modules/es.array.slice.js";
45import "core-js/modules/es.symbol.js";
46import "core-js/modules/es.symbol.description.js";
47import "core-js/modules/es.symbol.iterator.js";
48import "core-js/modules/es.function.name.js";
49import "core-js/modules/es.array.from.js";
50
51function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
52
53function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
54
55function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
56
57import global from 'global';
58import * as EVENTS from '@storybook/core-events';
59import Channel from '@storybook/channels';
60import { logger, pretty } from '@storybook/client-logger';
61import { isJSON, parse, stringify } from 'telejson';
62import qs from 'qs';
63var globalWindow = global.window,
64 document = global.document,
65 location = global.location;
66export var KEY = 'storybook-channel';
67var defaultEventOptions = {
68 allowFunction: true,
69 maxDepth: 25
70}; // TODO: we should export a method for opening child windows here and keep track of em.
71// that way we can send postMessage to child windows as well, not just iframe
72// https://stackoverflow.com/questions/6340160/how-to-get-the-references-of-all-already-opened-child-windows
73
74export var PostmsgTransport = /*#__PURE__*/function () {
75 function PostmsgTransport(config) {
76 _classCallCheck(this, PostmsgTransport);
77
78 this.config = config;
79 this.buffer = void 0;
80 this.handler = void 0;
81 this.connected = void 0;
82 this.buffer = [];
83 this.handler = null;
84 globalWindow.addEventListener('message', this.handleEvent.bind(this), false); // Check whether the config.page parameter has a valid value
85
86 if (config.page !== 'manager' && config.page !== 'preview') {
87 throw new Error("postmsg-channel: \"config.page\" cannot be \"".concat(config.page, "\""));
88 }
89 }
90
91 _createClass(PostmsgTransport, [{
92 key: "setHandler",
93 value: function setHandler(handler) {
94 var _this = this;
95
96 this.handler = function () {
97 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
98 args[_key] = arguments[_key];
99 }
100
101 handler.apply(_this, args);
102
103 if (!_this.connected && _this.getLocalFrame().length) {
104 _this.flush();
105
106 _this.connected = true;
107 }
108 };
109 }
110 /**
111 * Sends `event` to the associated window. If the window does not yet exist
112 * the event will be stored in a buffer and sent when the window exists.
113 * @param event
114 */
115
116 }, {
117 key: "send",
118 value: function send(event, options) {
119 var _this2 = this;
120
121 var _ref = options || {},
122 target = _ref.target,
123 allowRegExp = _ref.allowRegExp,
124 allowFunction = _ref.allowFunction,
125 allowSymbol = _ref.allowSymbol,
126 allowDate = _ref.allowDate,
127 allowUndefined = _ref.allowUndefined,
128 allowClass = _ref.allowClass,
129 maxDepth = _ref.maxDepth,
130 space = _ref.space,
131 lazyEval = _ref.lazyEval;
132
133 var eventOptions = Object.fromEntries(Object.entries({
134 allowRegExp: allowRegExp,
135 allowFunction: allowFunction,
136 allowSymbol: allowSymbol,
137 allowDate: allowDate,
138 allowUndefined: allowUndefined,
139 allowClass: allowClass,
140 maxDepth: maxDepth,
141 space: space,
142 lazyEval: lazyEval
143 }).filter(function (_ref2) {
144 var _ref3 = _slicedToArray(_ref2, 2),
145 k = _ref3[0],
146 v = _ref3[1];
147
148 return typeof v !== 'undefined';
149 }));
150 var stringifyOptions = Object.assign({}, defaultEventOptions, global.CHANNEL_OPTIONS || {}, eventOptions); // backwards compat: convert depth to maxDepth
151
152 if (options && Number.isInteger(options.depth)) {
153 stringifyOptions.maxDepth = options.depth;
154 }
155
156 var frames = this.getFrames(target);
157 var query = qs.parse(location.search, {
158 ignoreQueryPrefix: true
159 });
160 var data = stringify({
161 key: KEY,
162 event: event,
163 refId: query.refId
164 }, stringifyOptions);
165
166 if (!frames.length) {
167 return new Promise(function (resolve, reject) {
168 _this2.buffer.push({
169 event: event,
170 resolve: resolve,
171 reject: reject
172 });
173 });
174 }
175
176 if (this.buffer.length) {
177 this.flush();
178 }
179
180 frames.forEach(function (f) {
181 try {
182 f.postMessage(data, '*');
183 } catch (e) {
184 console.error('sending over postmessage fail');
185 }
186 });
187 return Promise.resolve(null);
188 }
189 }, {
190 key: "flush",
191 value: function flush() {
192 var _this3 = this;
193
194 var buffer = this.buffer;
195 this.buffer = [];
196 buffer.forEach(function (item) {
197 _this3.send(item.event).then(item.resolve).catch(item.reject);
198 });
199 }
200 }, {
201 key: "getFrames",
202 value: function getFrames(target) {
203 if (this.config.page === 'manager') {
204 var nodes = _toConsumableArray(document.querySelectorAll('iframe[data-is-storybook][data-is-loaded]'));
205
206 var list = nodes.filter(function (e) {
207 try {
208 return !!e.contentWindow && e.dataset.isStorybook !== undefined && e.id === target;
209 } catch (er) {
210 return false;
211 }
212 }).map(function (e) {
213 return e.contentWindow;
214 });
215 return list.length ? list : this.getCurrentFrames();
216 }
217
218 if (globalWindow && globalWindow.parent && globalWindow.parent !== globalWindow) {
219 return [globalWindow.parent];
220 }
221
222 return [];
223 }
224 }, {
225 key: "getCurrentFrames",
226 value: function getCurrentFrames() {
227 if (this.config.page === 'manager') {
228 var list = _toConsumableArray(document.querySelectorAll('[data-is-storybook="true"]'));
229
230 return list.map(function (e) {
231 return e.contentWindow;
232 });
233 }
234
235 if (globalWindow && globalWindow.parent) {
236 return [globalWindow.parent];
237 }
238
239 return [];
240 }
241 }, {
242 key: "getLocalFrame",
243 value: function getLocalFrame() {
244 if (this.config.page === 'manager') {
245 var list = _toConsumableArray(document.querySelectorAll('#storybook-preview-iframe'));
246
247 return list.map(function (e) {
248 return e.contentWindow;
249 });
250 }
251
252 if (globalWindow && globalWindow.parent) {
253 return [globalWindow.parent];
254 }
255
256 return [];
257 }
258 }, {
259 key: "handleEvent",
260 value: function handleEvent(rawEvent) {
261 try {
262 var data = rawEvent.data;
263
264 var _ref4 = typeof data === 'string' && isJSON(data) ? parse(data, global.CHANNEL_OPTIONS || {}) : data,
265 key = _ref4.key,
266 event = _ref4.event,
267 refId = _ref4.refId;
268
269 if (key === KEY) {
270 var pageString = this.config.page === 'manager' ? "<span style=\"color: #37D5D3; background: black\"> manager </span>" : "<span style=\"color: #1EA7FD; background: black\"> preview </span>";
271 var eventString = Object.values(EVENTS).includes(event.type) ? "<span style=\"color: #FF4785\">".concat(event.type, "</span>") : "<span style=\"color: #FFAE00\">".concat(event.type, "</span>");
272
273 if (refId) {
274 event.refId = refId;
275 }
276
277 event.source = this.config.page === 'preview' ? rawEvent.origin : getEventSourceUrl(rawEvent);
278
279 if (!event.source) {
280 pretty.error("".concat(pageString, " received ").concat(eventString, " but was unable to determine the source of the event"));
281 return;
282 }
283
284 var message = "".concat(pageString, " received ").concat(eventString, " (").concat(data.length, ")");
285 pretty.debug.apply(pretty, [location.origin !== event.source ? message : "".concat(message, " <span style=\"color: gray\">(on ").concat(location.origin, " from ").concat(event.source, ")</span>")].concat(_toConsumableArray(event.args)));
286 this.handler(event);
287 }
288 } catch (error) {
289 logger.error(error);
290 }
291 }
292 }]);
293
294 return PostmsgTransport;
295}();
296
297var getEventSourceUrl = function getEventSourceUrl(event) {
298 var frames = _toConsumableArray(document.querySelectorAll('iframe[data-is-storybook]')); // try to find the originating iframe by matching it's contentWindow
299 // This might not be cross-origin safe
300
301
302 var _frames$filter = frames.filter(function (element) {
303 try {
304 return element.contentWindow === event.source;
305 } catch (err) {// continue
306 }
307
308 var src = element.getAttribute('src');
309 var origin;
310
311 try {
312 var _URL = new URL(src, document.location);
313
314 origin = _URL.origin;
315 } catch (err) {
316 return false;
317 }
318
319 return origin === event.origin;
320 }),
321 _frames$filter2 = _toArray(_frames$filter),
322 frame = _frames$filter2[0],
323 remainder = _frames$filter2.slice(1);
324
325 if (frame && remainder.length === 0) {
326 var src = frame.getAttribute('src');
327
328 var _URL2 = new URL(src, document.location),
329 protocol = _URL2.protocol,
330 host = _URL2.host,
331 pathname = _URL2.pathname;
332
333 return "".concat(protocol, "//").concat(host).concat(pathname);
334 }
335
336 if (remainder.length > 0) {
337 // If we found multiple matches, there's going to be trouble
338 logger.error('found multiple candidates for event source');
339 } // If we found no frames of matches
340
341
342 return null;
343};
344/**
345 * Creates a channel which communicates with an iframe or child window.
346 */
347
348
349export default function createChannel(_ref5) {
350 var page = _ref5.page;
351 var transport = new PostmsgTransport({
352 page: page
353 });
354 return new Channel({
355 transport: transport
356 });
357}
\No newline at end of file