@usecsv/vuejs 1.0.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/CHANGELOG.md +6 -0
- package/README.md +4 -0
- package/dist/types/src/entry.esm.d.ts +5 -0
- package/dist/types/src/usecsv.vue.d.ts +16 -0
- package/dist/usecsv.esm.js +826 -0
- package/dist/usecsv.min.js +6 -0
- package/dist/usecsv.ssr.js +856 -0
- package/package.json +70 -0
- package/src/usecsv.vue +64 -0
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
'use strict';var Vue=require('vue');function _interopDefaultLegacy(e){return e&&typeof e==='object'&&'default'in e?e:{'default':e}}var Vue__default=/*#__PURE__*/_interopDefaultLegacy(Vue);function _slicedToArray(arr, i) {
|
|
2
|
+
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function _arrayWithHoles(arr) {
|
|
6
|
+
if (Array.isArray(arr)) return arr;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function _iterableToArrayLimit(arr, i) {
|
|
10
|
+
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
11
|
+
|
|
12
|
+
if (_i == null) return;
|
|
13
|
+
var _arr = [];
|
|
14
|
+
var _n = true;
|
|
15
|
+
var _d = false;
|
|
16
|
+
|
|
17
|
+
var _s, _e;
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
|
|
21
|
+
_arr.push(_s.value);
|
|
22
|
+
|
|
23
|
+
if (i && _arr.length === i) break;
|
|
24
|
+
}
|
|
25
|
+
} catch (err) {
|
|
26
|
+
_d = true;
|
|
27
|
+
_e = err;
|
|
28
|
+
} finally {
|
|
29
|
+
try {
|
|
30
|
+
if (!_n && _i["return"] != null) _i["return"]();
|
|
31
|
+
} finally {
|
|
32
|
+
if (_d) throw _e;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return _arr;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function _unsupportedIterableToArray(o, minLen) {
|
|
40
|
+
if (!o) return;
|
|
41
|
+
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
|
42
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
43
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
44
|
+
if (n === "Map" || n === "Set") return Array.from(o);
|
|
45
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function _arrayLikeToArray(arr, len) {
|
|
49
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
50
|
+
|
|
51
|
+
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
|
52
|
+
|
|
53
|
+
return arr2;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function _nonIterableRest() {
|
|
57
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
58
|
+
}/*!
|
|
59
|
+
* @usecsv/js v0.1.0
|
|
60
|
+
* (c) layercode
|
|
61
|
+
* Released under the MIT License.
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
var containers = []; // will store container HTMLElement references
|
|
65
|
+
var styleElements = []; // will store {prepend: HTMLElement, append: HTMLElement}
|
|
66
|
+
|
|
67
|
+
var usage = 'insert-css: You need to provide a CSS string. Usage: insertCss(cssString[, options]).';
|
|
68
|
+
|
|
69
|
+
function insertCss(css, options) {
|
|
70
|
+
options = options || {};
|
|
71
|
+
|
|
72
|
+
if (css === undefined) {
|
|
73
|
+
throw new Error(usage);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
var position = options.prepend === true ? 'prepend' : 'append';
|
|
77
|
+
var container = options.container !== undefined ? options.container : document.querySelector('head');
|
|
78
|
+
var containerId = containers.indexOf(container);
|
|
79
|
+
|
|
80
|
+
// first time we see this container, create the necessary entries
|
|
81
|
+
if (containerId === -1) {
|
|
82
|
+
containerId = containers.push(container) - 1;
|
|
83
|
+
styleElements[containerId] = {};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// try to get the correponding container + position styleElement, create it otherwise
|
|
87
|
+
var styleElement;
|
|
88
|
+
|
|
89
|
+
if (styleElements[containerId] !== undefined && styleElements[containerId][position] !== undefined) {
|
|
90
|
+
styleElement = styleElements[containerId][position];
|
|
91
|
+
} else {
|
|
92
|
+
styleElement = styleElements[containerId][position] = createStyleElement();
|
|
93
|
+
|
|
94
|
+
if (position === 'prepend') {
|
|
95
|
+
container.insertBefore(styleElement, container.childNodes[0]);
|
|
96
|
+
} else {
|
|
97
|
+
container.appendChild(styleElement);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// strip potential UTF-8 BOM if css was read from a file
|
|
102
|
+
if (css.charCodeAt(0) === 0xFEFF) { css = css.substr(1, css.length); }
|
|
103
|
+
|
|
104
|
+
// actually add the stylesheet
|
|
105
|
+
if (styleElement.styleSheet) {
|
|
106
|
+
styleElement.styleSheet.cssText += css;
|
|
107
|
+
} else {
|
|
108
|
+
styleElement.textContent += css;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return styleElement;
|
|
112
|
+
}
|
|
113
|
+
function createStyleElement() {
|
|
114
|
+
var styleElement = document.createElement('style');
|
|
115
|
+
styleElement.setAttribute('type', 'text/css');
|
|
116
|
+
return styleElement;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
var insertCss_1 = insertCss;
|
|
120
|
+
var insertCss_2 = insertCss;
|
|
121
|
+
insertCss_1.insertCss = insertCss_2;
|
|
122
|
+
|
|
123
|
+
var MessageType;
|
|
124
|
+
(function (MessageType) {
|
|
125
|
+
MessageType["Call"] = "call";
|
|
126
|
+
MessageType["Reply"] = "reply";
|
|
127
|
+
MessageType["Syn"] = "syn";
|
|
128
|
+
MessageType["SynAck"] = "synAck";
|
|
129
|
+
MessageType["Ack"] = "ack";
|
|
130
|
+
})(MessageType || (MessageType = {}));
|
|
131
|
+
var Resolution;
|
|
132
|
+
(function (Resolution) {
|
|
133
|
+
Resolution["Fulfilled"] = "fulfilled";
|
|
134
|
+
Resolution["Rejected"] = "rejected";
|
|
135
|
+
})(Resolution || (Resolution = {}));
|
|
136
|
+
var ErrorCode;
|
|
137
|
+
(function (ErrorCode) {
|
|
138
|
+
ErrorCode["ConnectionDestroyed"] = "ConnectionDestroyed";
|
|
139
|
+
ErrorCode["ConnectionTimeout"] = "ConnectionTimeout";
|
|
140
|
+
ErrorCode["NoIframeSrc"] = "NoIframeSrc";
|
|
141
|
+
})(ErrorCode || (ErrorCode = {}));
|
|
142
|
+
var NativeErrorName;
|
|
143
|
+
(function (NativeErrorName) {
|
|
144
|
+
NativeErrorName["DataCloneError"] = "DataCloneError";
|
|
145
|
+
})(NativeErrorName || (NativeErrorName = {}));
|
|
146
|
+
var NativeEventType;
|
|
147
|
+
(function (NativeEventType) {
|
|
148
|
+
NativeEventType["Message"] = "message";
|
|
149
|
+
})(NativeEventType || (NativeEventType = {}));
|
|
150
|
+
|
|
151
|
+
var createDestructor = (localName, log) => {
|
|
152
|
+
const callbacks = [];
|
|
153
|
+
let destroyed = false;
|
|
154
|
+
return {
|
|
155
|
+
destroy(error) {
|
|
156
|
+
if (!destroyed) {
|
|
157
|
+
destroyed = true;
|
|
158
|
+
log(`${localName}: Destroying connection`);
|
|
159
|
+
callbacks.forEach((callback) => {
|
|
160
|
+
callback(error);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
onDestroy(callback) {
|
|
165
|
+
destroyed ? callback() : callbacks.push(callback);
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
var createLogger = (debug) => {
|
|
171
|
+
/**
|
|
172
|
+
* Logs a message if debug is enabled.
|
|
173
|
+
*/
|
|
174
|
+
return (...args) => {
|
|
175
|
+
if (debug) {
|
|
176
|
+
console.log('[Penpal]', ...args); // eslint-disable-line no-console
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const DEFAULT_PORT_BY_PROTOCOL = {
|
|
182
|
+
'http:': '80',
|
|
183
|
+
'https:': '443',
|
|
184
|
+
};
|
|
185
|
+
const URL_REGEX = /^(https?:)?\/\/([^/:]+)?(:(\d+))?/;
|
|
186
|
+
const opaqueOriginSchemes = ['file:', 'data:'];
|
|
187
|
+
/**
|
|
188
|
+
* Converts a src value into an origin.
|
|
189
|
+
*/
|
|
190
|
+
var getOriginFromSrc = (src) => {
|
|
191
|
+
if (src && opaqueOriginSchemes.find((scheme) => src.startsWith(scheme))) {
|
|
192
|
+
// The origin of the child document is an opaque origin and its
|
|
193
|
+
// serialization is "null"
|
|
194
|
+
// https://html.spec.whatwg.org/multipage/origin.html#origin
|
|
195
|
+
return 'null';
|
|
196
|
+
}
|
|
197
|
+
// Note that if src is undefined, then srcdoc is being used instead of src
|
|
198
|
+
// and we can follow this same logic below to get the origin of the parent,
|
|
199
|
+
// which is the origin that we will need to use.
|
|
200
|
+
const location = document.location;
|
|
201
|
+
const regexResult = URL_REGEX.exec(src);
|
|
202
|
+
let protocol;
|
|
203
|
+
let hostname;
|
|
204
|
+
let port;
|
|
205
|
+
if (regexResult) {
|
|
206
|
+
// It's an absolute URL. Use the parsed info.
|
|
207
|
+
// regexResult[1] will be undefined if the URL starts with //
|
|
208
|
+
protocol = regexResult[1] ? regexResult[1] : location.protocol;
|
|
209
|
+
hostname = regexResult[2];
|
|
210
|
+
port = regexResult[4];
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
// It's a relative path. Use the current location's info.
|
|
214
|
+
protocol = location.protocol;
|
|
215
|
+
hostname = location.hostname;
|
|
216
|
+
port = location.port;
|
|
217
|
+
}
|
|
218
|
+
// If the port is the default for the protocol, we don't want to add it to the origin string
|
|
219
|
+
// or it won't match the message's event.origin.
|
|
220
|
+
const portSuffix = port && port !== DEFAULT_PORT_BY_PROTOCOL[protocol] ? `:${port}` : '';
|
|
221
|
+
return `${protocol}//${hostname}${portSuffix}`;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Converts an error object into a plain object.
|
|
226
|
+
*/
|
|
227
|
+
const serializeError = ({ name, message, stack, }) => ({
|
|
228
|
+
name,
|
|
229
|
+
message,
|
|
230
|
+
stack,
|
|
231
|
+
});
|
|
232
|
+
/**
|
|
233
|
+
* Converts a plain object into an error object.
|
|
234
|
+
*/
|
|
235
|
+
const deserializeError = (obj) => {
|
|
236
|
+
const deserializedError = new Error();
|
|
237
|
+
// @ts-ignore
|
|
238
|
+
Object.keys(obj).forEach((key) => (deserializedError[key] = obj[key]));
|
|
239
|
+
return deserializedError;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Listens for "call" messages coming from the remote, executes the corresponding method, and
|
|
244
|
+
* responds with the return value.
|
|
245
|
+
*/
|
|
246
|
+
var connectCallReceiver = (info, methods, log) => {
|
|
247
|
+
const { localName, local, remote, originForSending, originForReceiving, } = info;
|
|
248
|
+
let destroyed = false;
|
|
249
|
+
const handleMessageEvent = (event) => {
|
|
250
|
+
if (event.source !== remote || event.data.penpal !== MessageType.Call) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (event.origin !== originForReceiving) {
|
|
254
|
+
log(`${localName} received message from origin ${event.origin} which did not match expected origin ${originForReceiving}`);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const callMessage = event.data;
|
|
258
|
+
const { methodName, args, id } = callMessage;
|
|
259
|
+
log(`${localName}: Received ${methodName}() call`);
|
|
260
|
+
const createPromiseHandler = (resolution) => {
|
|
261
|
+
return (returnValue) => {
|
|
262
|
+
log(`${localName}: Sending ${methodName}() reply`);
|
|
263
|
+
if (destroyed) {
|
|
264
|
+
// It's possible to throw an error here, but it would need to be thrown asynchronously
|
|
265
|
+
// and would only be catchable using window.onerror. This is because the consumer
|
|
266
|
+
// is merely returning a value from their method and not calling any function
|
|
267
|
+
// that they could wrap in a try-catch. Even if the consumer were to catch the error,
|
|
268
|
+
// the value of doing so is questionable. Instead, we'll just log a message.
|
|
269
|
+
log(`${localName}: Unable to send ${methodName}() reply due to destroyed connection`);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const message = {
|
|
273
|
+
penpal: MessageType.Reply,
|
|
274
|
+
id,
|
|
275
|
+
resolution,
|
|
276
|
+
returnValue,
|
|
277
|
+
};
|
|
278
|
+
if (resolution === Resolution.Rejected &&
|
|
279
|
+
returnValue instanceof Error) {
|
|
280
|
+
message.returnValue = serializeError(returnValue);
|
|
281
|
+
message.returnValueIsError = true;
|
|
282
|
+
}
|
|
283
|
+
try {
|
|
284
|
+
remote.postMessage(message, originForSending);
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
// If a consumer attempts to send an object that's not cloneable (e.g., window),
|
|
288
|
+
// we want to ensure the receiver's promise gets rejected.
|
|
289
|
+
if (err.name === NativeErrorName.DataCloneError) {
|
|
290
|
+
const errorReplyMessage = {
|
|
291
|
+
penpal: MessageType.Reply,
|
|
292
|
+
id,
|
|
293
|
+
resolution: Resolution.Rejected,
|
|
294
|
+
returnValue: serializeError(err),
|
|
295
|
+
returnValueIsError: true,
|
|
296
|
+
};
|
|
297
|
+
remote.postMessage(errorReplyMessage, originForSending);
|
|
298
|
+
}
|
|
299
|
+
throw err;
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
};
|
|
303
|
+
new Promise((resolve) => resolve(methods[methodName].apply(methods, args))).then(createPromiseHandler(Resolution.Fulfilled), createPromiseHandler(Resolution.Rejected));
|
|
304
|
+
};
|
|
305
|
+
local.addEventListener(NativeEventType.Message, handleMessageEvent);
|
|
306
|
+
return () => {
|
|
307
|
+
destroyed = true;
|
|
308
|
+
local.removeEventListener(NativeEventType.Message, handleMessageEvent);
|
|
309
|
+
};
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
let id = 0;
|
|
313
|
+
/**
|
|
314
|
+
* @return {number} A unique ID (not universally unique)
|
|
315
|
+
*/
|
|
316
|
+
var generateId = () => ++id;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Augments an object with methods that match those defined by the remote. When these methods are
|
|
320
|
+
* called, a "call" message will be sent to the remote, the remote's corresponding method will be
|
|
321
|
+
* executed, and the method's return value will be returned via a message.
|
|
322
|
+
* @param {Object} callSender Sender object that should be augmented with methods.
|
|
323
|
+
* @param {Object} info Information about the local and remote windows.
|
|
324
|
+
* @param {Array} methodNames Names of methods available to be called on the remote.
|
|
325
|
+
* @param {Promise} destructionPromise A promise resolved when destroy() is called on the penpal
|
|
326
|
+
* connection.
|
|
327
|
+
* @returns {Object} The call sender object with methods that may be called.
|
|
328
|
+
*/
|
|
329
|
+
var connectCallSender = (callSender, info, methodNames, destroyConnection, log) => {
|
|
330
|
+
const { localName, local, remote, originForSending, originForReceiving, } = info;
|
|
331
|
+
let destroyed = false;
|
|
332
|
+
log(`${localName}: Connecting call sender`);
|
|
333
|
+
const createMethodProxy = (methodName) => {
|
|
334
|
+
return (...args) => {
|
|
335
|
+
log(`${localName}: Sending ${methodName}() call`);
|
|
336
|
+
// This handles the case where the iframe has been removed from the DOM
|
|
337
|
+
// (and therefore its window closed), the consumer has not yet
|
|
338
|
+
// called destroy(), and the user calls a method exposed by
|
|
339
|
+
// the remote. We detect the iframe has been removed and force
|
|
340
|
+
// a destroy() immediately so that the consumer sees the error saying
|
|
341
|
+
// the connection has been destroyed. We wrap this check in a try catch
|
|
342
|
+
// because Edge throws an "Object expected" error when accessing
|
|
343
|
+
// contentWindow.closed on a contentWindow from an iframe that's been
|
|
344
|
+
// removed from the DOM.
|
|
345
|
+
let iframeRemoved;
|
|
346
|
+
try {
|
|
347
|
+
if (remote.closed) {
|
|
348
|
+
iframeRemoved = true;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
catch (e) {
|
|
352
|
+
iframeRemoved = true;
|
|
353
|
+
}
|
|
354
|
+
if (iframeRemoved) {
|
|
355
|
+
destroyConnection();
|
|
356
|
+
}
|
|
357
|
+
if (destroyed) {
|
|
358
|
+
const error = new Error(`Unable to send ${methodName}() call due ` + `to destroyed connection`);
|
|
359
|
+
error.code = ErrorCode.ConnectionDestroyed;
|
|
360
|
+
throw error;
|
|
361
|
+
}
|
|
362
|
+
return new Promise((resolve, reject) => {
|
|
363
|
+
const id = generateId();
|
|
364
|
+
const handleMessageEvent = (event) => {
|
|
365
|
+
if (event.source !== remote ||
|
|
366
|
+
event.data.penpal !== MessageType.Reply ||
|
|
367
|
+
event.data.id !== id) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
if (event.origin !== originForReceiving) {
|
|
371
|
+
log(`${localName} received message from origin ${event.origin} which did not match expected origin ${originForReceiving}`);
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
const replyMessage = event.data;
|
|
375
|
+
log(`${localName}: Received ${methodName}() reply`);
|
|
376
|
+
local.removeEventListener(NativeEventType.Message, handleMessageEvent);
|
|
377
|
+
let returnValue = replyMessage.returnValue;
|
|
378
|
+
if (replyMessage.returnValueIsError) {
|
|
379
|
+
returnValue = deserializeError(returnValue);
|
|
380
|
+
}
|
|
381
|
+
(replyMessage.resolution === Resolution.Fulfilled ? resolve : reject)(returnValue);
|
|
382
|
+
};
|
|
383
|
+
local.addEventListener(NativeEventType.Message, handleMessageEvent);
|
|
384
|
+
const callMessage = {
|
|
385
|
+
penpal: MessageType.Call,
|
|
386
|
+
id,
|
|
387
|
+
methodName,
|
|
388
|
+
args,
|
|
389
|
+
};
|
|
390
|
+
remote.postMessage(callMessage, originForSending);
|
|
391
|
+
});
|
|
392
|
+
};
|
|
393
|
+
};
|
|
394
|
+
methodNames.reduce((api, methodName) => {
|
|
395
|
+
api[methodName] = createMethodProxy(methodName);
|
|
396
|
+
return api;
|
|
397
|
+
}, callSender);
|
|
398
|
+
return () => {
|
|
399
|
+
destroyed = true;
|
|
400
|
+
};
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Handles an ACK handshake message.
|
|
405
|
+
*/
|
|
406
|
+
var handleAckMessageFactory = (methods, childOrigin, originForSending, destructor, log) => {
|
|
407
|
+
const { destroy, onDestroy } = destructor;
|
|
408
|
+
let destroyCallReceiver;
|
|
409
|
+
let receiverMethodNames;
|
|
410
|
+
// We resolve the promise with the call sender. If the child reconnects
|
|
411
|
+
// (for example, after refreshing or navigating to another page that
|
|
412
|
+
// uses Penpal, we'll update the call sender with methods that match the
|
|
413
|
+
// latest provided by the child.
|
|
414
|
+
const callSender = {};
|
|
415
|
+
return (event) => {
|
|
416
|
+
if (event.origin !== childOrigin) {
|
|
417
|
+
log(`Parent: Handshake - Received ACK message from origin ${event.origin} which did not match expected origin ${childOrigin}`);
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
log('Parent: Handshake - Received ACK');
|
|
421
|
+
const info = {
|
|
422
|
+
localName: 'Parent',
|
|
423
|
+
local: window,
|
|
424
|
+
remote: event.source,
|
|
425
|
+
originForSending: originForSending,
|
|
426
|
+
originForReceiving: childOrigin,
|
|
427
|
+
};
|
|
428
|
+
// If the child reconnected, we need to destroy the prior call receiver
|
|
429
|
+
// before setting up a new one.
|
|
430
|
+
if (destroyCallReceiver) {
|
|
431
|
+
destroyCallReceiver();
|
|
432
|
+
}
|
|
433
|
+
destroyCallReceiver = connectCallReceiver(info, methods, log);
|
|
434
|
+
onDestroy(destroyCallReceiver);
|
|
435
|
+
// If the child reconnected, we need to remove the methods from the
|
|
436
|
+
// previous call receiver off the sender.
|
|
437
|
+
if (receiverMethodNames) {
|
|
438
|
+
receiverMethodNames.forEach((receiverMethodName) => {
|
|
439
|
+
delete callSender[receiverMethodName];
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
receiverMethodNames = event.data.methodNames;
|
|
443
|
+
const destroyCallSender = connectCallSender(callSender, info, receiverMethodNames, destroy, log);
|
|
444
|
+
onDestroy(destroyCallSender);
|
|
445
|
+
return callSender;
|
|
446
|
+
};
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Handles a SYN handshake message.
|
|
451
|
+
*/
|
|
452
|
+
var handleSynMessageFactory = (log, methods, childOrigin, originForSending) => {
|
|
453
|
+
return (event) => {
|
|
454
|
+
if (event.origin !== childOrigin) {
|
|
455
|
+
log(`Parent: Handshake - Received SYN message from origin ${event.origin} which did not match expected origin ${childOrigin}`);
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
log('Parent: Handshake - Received SYN, responding with SYN-ACK');
|
|
459
|
+
const synAckMessage = {
|
|
460
|
+
penpal: MessageType.SynAck,
|
|
461
|
+
methodNames: Object.keys(methods),
|
|
462
|
+
};
|
|
463
|
+
event.source.postMessage(synAckMessage, originForSending);
|
|
464
|
+
};
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
const CHECK_IFRAME_IN_DOC_INTERVAL = 60000;
|
|
468
|
+
/**
|
|
469
|
+
* Monitors for iframe removal and destroys connection if iframe
|
|
470
|
+
* is found to have been removed from DOM. This is to prevent memory
|
|
471
|
+
* leaks when the iframe is removed from the document and the consumer
|
|
472
|
+
* hasn't called destroy(). Without this, event listeners attached to
|
|
473
|
+
* the window would stick around and since the event handlers have a
|
|
474
|
+
* reference to the iframe in their closures, the iframe would stick
|
|
475
|
+
* around too.
|
|
476
|
+
*/
|
|
477
|
+
var monitorIframeRemoval = (iframe, destructor) => {
|
|
478
|
+
const { destroy, onDestroy } = destructor;
|
|
479
|
+
const checkIframeInDocIntervalId = setInterval(() => {
|
|
480
|
+
if (!iframe.isConnected) {
|
|
481
|
+
clearInterval(checkIframeInDocIntervalId);
|
|
482
|
+
destroy();
|
|
483
|
+
}
|
|
484
|
+
}, CHECK_IFRAME_IN_DOC_INTERVAL);
|
|
485
|
+
onDestroy(() => {
|
|
486
|
+
clearInterval(checkIframeInDocIntervalId);
|
|
487
|
+
});
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Starts a timeout and calls the callback with an error
|
|
492
|
+
* if the timeout completes before the stop function is called.
|
|
493
|
+
*/
|
|
494
|
+
var startConnectionTimeout = (timeout, callback) => {
|
|
495
|
+
let timeoutId;
|
|
496
|
+
if (timeout !== undefined) {
|
|
497
|
+
timeoutId = window.setTimeout(() => {
|
|
498
|
+
const error = new Error(`Connection timed out after ${timeout}ms`);
|
|
499
|
+
error.code = ErrorCode.ConnectionTimeout;
|
|
500
|
+
callback(error);
|
|
501
|
+
}, timeout);
|
|
502
|
+
}
|
|
503
|
+
return () => {
|
|
504
|
+
clearTimeout(timeoutId);
|
|
505
|
+
};
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
var validateIframeHasSrcOrSrcDoc = (iframe) => {
|
|
509
|
+
if (!iframe.src && !iframe.srcdoc) {
|
|
510
|
+
const error = new Error('Iframe must have src or srcdoc property defined.');
|
|
511
|
+
error.code = ErrorCode.NoIframeSrc;
|
|
512
|
+
throw error;
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Attempts to establish communication with an iframe.
|
|
518
|
+
*/
|
|
519
|
+
var connectToChild = (options) => {
|
|
520
|
+
let { iframe, methods = {}, childOrigin, timeout, debug = false } = options;
|
|
521
|
+
const log = createLogger(debug);
|
|
522
|
+
const destructor = createDestructor('Parent', log);
|
|
523
|
+
const { onDestroy, destroy } = destructor;
|
|
524
|
+
if (!childOrigin) {
|
|
525
|
+
validateIframeHasSrcOrSrcDoc(iframe);
|
|
526
|
+
childOrigin = getOriginFromSrc(iframe.src);
|
|
527
|
+
}
|
|
528
|
+
// If event.origin is "null", the remote protocol is file: or data: and we
|
|
529
|
+
// must post messages with "*" as targetOrigin when sending messages.
|
|
530
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Using_window.postMessage_in_extensions
|
|
531
|
+
const originForSending = childOrigin === 'null' ? '*' : childOrigin;
|
|
532
|
+
const handleSynMessage = handleSynMessageFactory(log, methods, childOrigin, originForSending);
|
|
533
|
+
const handleAckMessage = handleAckMessageFactory(methods, childOrigin, originForSending, destructor, log);
|
|
534
|
+
const promise = new Promise((resolve, reject) => {
|
|
535
|
+
const stopConnectionTimeout = startConnectionTimeout(timeout, destroy);
|
|
536
|
+
const handleMessage = (event) => {
|
|
537
|
+
if (event.source !== iframe.contentWindow || !event.data) {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
if (event.data.penpal === MessageType.Syn) {
|
|
541
|
+
handleSynMessage(event);
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
if (event.data.penpal === MessageType.Ack) {
|
|
545
|
+
const callSender = handleAckMessage(event);
|
|
546
|
+
if (callSender) {
|
|
547
|
+
stopConnectionTimeout();
|
|
548
|
+
resolve(callSender);
|
|
549
|
+
}
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
window.addEventListener(NativeEventType.Message, handleMessage);
|
|
554
|
+
log('Parent: Awaiting handshake');
|
|
555
|
+
monitorIframeRemoval(iframe, destructor);
|
|
556
|
+
onDestroy((error) => {
|
|
557
|
+
window.removeEventListener(NativeEventType.Message, handleMessage);
|
|
558
|
+
if (error) {
|
|
559
|
+
reject(error);
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
});
|
|
563
|
+
return {
|
|
564
|
+
promise,
|
|
565
|
+
destroy() {
|
|
566
|
+
// Don't allow consumer to pass an error into destroy.
|
|
567
|
+
destroy();
|
|
568
|
+
},
|
|
569
|
+
};
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
/* eslint no-void: "off" */
|
|
573
|
+
|
|
574
|
+
// Loaded ready states
|
|
575
|
+
var loadedStates = ['interactive', 'complete'];
|
|
576
|
+
|
|
577
|
+
// Return Promise
|
|
578
|
+
var whenDomReady = function whenDomReady(cb, doc) {
|
|
579
|
+
return new Promise(function (resolve) {
|
|
580
|
+
// Allow doc to be passed in as the lone first param
|
|
581
|
+
if (cb && typeof cb !== 'function') {
|
|
582
|
+
doc = cb;
|
|
583
|
+
cb = null;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// Use global document if we don't have one
|
|
587
|
+
doc = doc || window.document;
|
|
588
|
+
|
|
589
|
+
// Handle DOM load
|
|
590
|
+
var done = function done() {
|
|
591
|
+
return resolve(void (cb && setTimeout(cb)));
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
// Resolve now if DOM has already loaded
|
|
595
|
+
// Otherwise wait for DOMContentLoaded
|
|
596
|
+
if (loadedStates.indexOf(doc.readyState) !== -1) {
|
|
597
|
+
done();
|
|
598
|
+
} else {
|
|
599
|
+
doc.addEventListener('DOMContentLoaded', done);
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
// Promise chain helper
|
|
605
|
+
whenDomReady.resume = function (doc) {
|
|
606
|
+
return function (val) {
|
|
607
|
+
return whenDomReady(doc).then(function () {
|
|
608
|
+
return val;
|
|
609
|
+
});
|
|
610
|
+
};
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
// eslint-disable-next-line dot-notation
|
|
614
|
+
var MOUNT_URL = {"MOUNT_URL":"https://app.usecsv.com/importer"}["MOUNT_URL"] ;
|
|
615
|
+
var insertIframe = function (id) {
|
|
616
|
+
var _a;
|
|
617
|
+
insertCss_2("\n .usecsv_container {\n position: fixed;\n top: 0;\n bottom: 0;\n right: 0;\n left: 0;\n z-index: 100000;\n }\n .usecsv_container iframe {\n width: 100%;\n height: 100%;\n position: absolute;\n border-width: 0;\n }\n .usecsv_container {\n overflow: hidden;\n overscroll-behavior-x: none;\n }\n");
|
|
618
|
+
document.body.insertAdjacentHTML("beforeend", "<div id=".concat(id, " class=\"usecsv_container loading\">\n</div>"));
|
|
619
|
+
var iframe = document.createElement("iframe");
|
|
620
|
+
iframe.setAttribute("src", MOUNT_URL);
|
|
621
|
+
(_a = document.getElementById(id)) === null || _a === void 0 ? void 0 : _a.appendChild(iframe);
|
|
622
|
+
return iframe;
|
|
623
|
+
};
|
|
624
|
+
var useCsvPlugin = function (_a) {
|
|
625
|
+
var importerKey = _a.importerKey, user = _a.user, metadata = _a.metadata;
|
|
626
|
+
var id = "usecsv-".concat(Math.round(Math.random() * 100000000));
|
|
627
|
+
return whenDomReady().then(function () {
|
|
628
|
+
var iframe = insertIframe(id);
|
|
629
|
+
var iframeConnection = connectToChild({
|
|
630
|
+
iframe: iframe,
|
|
631
|
+
methods: {
|
|
632
|
+
closeIframe: function () {
|
|
633
|
+
var _a;
|
|
634
|
+
(_a = document.getElementById(id)) === null || _a === void 0 ? void 0 : _a.remove();
|
|
635
|
+
},
|
|
636
|
+
},
|
|
637
|
+
});
|
|
638
|
+
iframeConnection.promise.then(function (child) {
|
|
639
|
+
var _a;
|
|
640
|
+
(_a = document.getElementById(id)) === null || _a === void 0 ? void 0 : _a.classList.remove("loading");
|
|
641
|
+
// eslint-disable-next-line dot-notation
|
|
642
|
+
child["setParams"] && child["setParams"]({ importerKey: importerKey, user: user, metadata: metadata });
|
|
643
|
+
});
|
|
644
|
+
return iframeConnection;
|
|
645
|
+
});
|
|
646
|
+
};var script = /*#__PURE__*/Vue__default["default"].extend({
|
|
647
|
+
name: "use-csv",
|
|
648
|
+
// vue component name
|
|
649
|
+
data: function data() {
|
|
650
|
+
return {
|
|
651
|
+
hasSlot: !!this.$slots.default
|
|
652
|
+
};
|
|
653
|
+
},
|
|
654
|
+
methods: {
|
|
655
|
+
onclick: function onclick() {
|
|
656
|
+
useCsvPlugin({
|
|
657
|
+
importerKey: this.importerKey,
|
|
658
|
+
user: this.importerKey,
|
|
659
|
+
metadata: this.metadata
|
|
660
|
+
});
|
|
661
|
+
},
|
|
662
|
+
hasScopedSlot: function hasScopedSlot() {
|
|
663
|
+
console.log(this.$scopedSlots.default && this.$scopedSlots.default.name);
|
|
664
|
+
return (this.$scopedSlots.default && this.$scopedSlots.default.name) === "normalized";
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
});function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
|
|
668
|
+
if (typeof shadowMode !== 'boolean') {
|
|
669
|
+
createInjectorSSR = createInjector;
|
|
670
|
+
createInjector = shadowMode;
|
|
671
|
+
shadowMode = false;
|
|
672
|
+
}
|
|
673
|
+
// Vue.extend constructor export interop.
|
|
674
|
+
const options = typeof script === 'function' ? script.options : script;
|
|
675
|
+
// render functions
|
|
676
|
+
if (template && template.render) {
|
|
677
|
+
options.render = template.render;
|
|
678
|
+
options.staticRenderFns = template.staticRenderFns;
|
|
679
|
+
options._compiled = true;
|
|
680
|
+
// functional template
|
|
681
|
+
if (isFunctionalTemplate) {
|
|
682
|
+
options.functional = true;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
// scopedId
|
|
686
|
+
if (scopeId) {
|
|
687
|
+
options._scopeId = scopeId;
|
|
688
|
+
}
|
|
689
|
+
let hook;
|
|
690
|
+
if (moduleIdentifier) {
|
|
691
|
+
// server build
|
|
692
|
+
hook = function (context) {
|
|
693
|
+
// 2.3 injection
|
|
694
|
+
context =
|
|
695
|
+
context || // cached call
|
|
696
|
+
(this.$vnode && this.$vnode.ssrContext) || // stateful
|
|
697
|
+
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional
|
|
698
|
+
// 2.2 with runInNewContext: true
|
|
699
|
+
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
|
|
700
|
+
context = __VUE_SSR_CONTEXT__;
|
|
701
|
+
}
|
|
702
|
+
// inject component styles
|
|
703
|
+
if (style) {
|
|
704
|
+
style.call(this, createInjectorSSR(context));
|
|
705
|
+
}
|
|
706
|
+
// register component module identifier for async chunk inference
|
|
707
|
+
if (context && context._registeredComponents) {
|
|
708
|
+
context._registeredComponents.add(moduleIdentifier);
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
// used by ssr in case component is cached and beforeCreate
|
|
712
|
+
// never gets called
|
|
713
|
+
options._ssrRegister = hook;
|
|
714
|
+
}
|
|
715
|
+
else if (style) {
|
|
716
|
+
hook = shadowMode
|
|
717
|
+
? function (context) {
|
|
718
|
+
style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot));
|
|
719
|
+
}
|
|
720
|
+
: function (context) {
|
|
721
|
+
style.call(this, createInjector(context));
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
if (hook) {
|
|
725
|
+
if (options.functional) {
|
|
726
|
+
// register for functional component in vue file
|
|
727
|
+
const originalRender = options.render;
|
|
728
|
+
options.render = function renderWithStyleInjection(h, context) {
|
|
729
|
+
hook.call(context);
|
|
730
|
+
return originalRender(h, context);
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
// inject component registration as beforeCreate hook
|
|
735
|
+
const existing = options.beforeCreate;
|
|
736
|
+
options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
return script;
|
|
740
|
+
}function createInjectorSSR(context) {
|
|
741
|
+
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
|
|
742
|
+
context = __VUE_SSR_CONTEXT__;
|
|
743
|
+
}
|
|
744
|
+
if (!context)
|
|
745
|
+
return () => { };
|
|
746
|
+
if (!('styles' in context)) {
|
|
747
|
+
context._styles = context._styles || {};
|
|
748
|
+
Object.defineProperty(context, 'styles', {
|
|
749
|
+
enumerable: true,
|
|
750
|
+
get: () => context._renderStyles(context._styles)
|
|
751
|
+
});
|
|
752
|
+
context._renderStyles = context._renderStyles || renderStyles;
|
|
753
|
+
}
|
|
754
|
+
return (id, style) => addStyle(id, style, context);
|
|
755
|
+
}
|
|
756
|
+
function addStyle(id, css, context) {
|
|
757
|
+
const group = css.media || 'default' ;
|
|
758
|
+
const style = context._styles[group] || (context._styles[group] = { ids: [], css: '' });
|
|
759
|
+
if (!style.ids.includes(id)) {
|
|
760
|
+
style.media = css.media;
|
|
761
|
+
style.ids.push(id);
|
|
762
|
+
let code = css.source;
|
|
763
|
+
style.css += code + '\n';
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
function renderStyles(styles) {
|
|
767
|
+
let css = '';
|
|
768
|
+
for (const key in styles) {
|
|
769
|
+
const style = styles[key];
|
|
770
|
+
css +=
|
|
771
|
+
'<style data-vue-ssr-id="' +
|
|
772
|
+
Array.from(style.ids).join(' ') +
|
|
773
|
+
'"' +
|
|
774
|
+
(style.media ? ' media="' + style.media + '"' : '') +
|
|
775
|
+
'>' +
|
|
776
|
+
style.css +
|
|
777
|
+
'</style>';
|
|
778
|
+
}
|
|
779
|
+
return css;
|
|
780
|
+
}/* script */
|
|
781
|
+
var __vue_script__ = script;
|
|
782
|
+
/* template */
|
|
783
|
+
|
|
784
|
+
var __vue_render__ = function __vue_render__() {
|
|
785
|
+
var _vm = this;
|
|
786
|
+
|
|
787
|
+
var _h = _vm.$createElement;
|
|
788
|
+
|
|
789
|
+
var _c = _vm._self._c || _h;
|
|
790
|
+
|
|
791
|
+
return _c('div', {
|
|
792
|
+
staticClass: "usecsv"
|
|
793
|
+
}, [_vm.hasScopedSlot() ? _vm._ssrNode("<div data-v-d2ea7b16>", "</div>", [_vm._t("default", function () {
|
|
794
|
+
return [_vm._v(" open usecsv ")];
|
|
795
|
+
}, {
|
|
796
|
+
"onclick": _vm.onclick
|
|
797
|
+
})], 2) : _vm._ssrNode("<div data-v-d2ea7b16>", "</div>", [_vm._ssrNode("<button type=\"button\" id=\"usecsv-button\" data-v-d2ea7b16>", "</button>", [_vm._t("default", function () {
|
|
798
|
+
return [_vm._v(" open usecsv ")];
|
|
799
|
+
})], 2)])]);
|
|
800
|
+
};
|
|
801
|
+
|
|
802
|
+
var __vue_staticRenderFns__ = [];
|
|
803
|
+
/* style */
|
|
804
|
+
|
|
805
|
+
var __vue_inject_styles__ = function __vue_inject_styles__(inject) {
|
|
806
|
+
if (!inject) return;
|
|
807
|
+
inject("data-v-d2ea7b16_0", {
|
|
808
|
+
source: "#usecsv-button[data-v-d2ea7b16]{background-color:#fff;color:#000;border:2px solid #000;border-radius:6px;padding:10px 15px;text-align:center;font-size:16px;cursor:pointer}",
|
|
809
|
+
map: undefined,
|
|
810
|
+
media: undefined
|
|
811
|
+
});
|
|
812
|
+
};
|
|
813
|
+
/* scoped */
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
var __vue_scope_id__ = "data-v-d2ea7b16";
|
|
817
|
+
/* module identifier */
|
|
818
|
+
|
|
819
|
+
var __vue_module_identifier__ = "data-v-d2ea7b16";
|
|
820
|
+
/* functional template */
|
|
821
|
+
|
|
822
|
+
var __vue_is_functional_template__ = false;
|
|
823
|
+
/* style inject shadow dom */
|
|
824
|
+
|
|
825
|
+
var __vue_component__ = /*#__PURE__*/normalizeComponent({
|
|
826
|
+
render: __vue_render__,
|
|
827
|
+
staticRenderFns: __vue_staticRenderFns__
|
|
828
|
+
}, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, false, undefined, createInjectorSSR, undefined);
|
|
829
|
+
|
|
830
|
+
var component$1 = __vue_component__;// Import vue component
|
|
831
|
+
|
|
832
|
+
// Default export is installable instance of component.
|
|
833
|
+
// IIFE injects install function into component, allowing component
|
|
834
|
+
// to be registered via Vue.use() as well as Vue.component(),
|
|
835
|
+
var component = /*#__PURE__*/(function () {
|
|
836
|
+
// Assign InstallableComponent type
|
|
837
|
+
var installable = component$1; // Attach install function executed by Vue.use()
|
|
838
|
+
|
|
839
|
+
installable.install = function (Vue) {
|
|
840
|
+
Vue.component('use-csv', installable);
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
return installable;
|
|
844
|
+
})(); // It's possible to expose named exports when writing components that can
|
|
845
|
+
// also be used as directives, etc. - eg. import { RollupDemoDirective } from 'rollup-demo';
|
|
846
|
+
// export const RollupDemoDirective = directive;
|
|
847
|
+
var namedExports=/*#__PURE__*/Object.freeze({__proto__:null,'default':component});// only expose one global var, with named exports exposed as properties of
|
|
848
|
+
// that global var (eg. plugin.namedExport)
|
|
849
|
+
|
|
850
|
+
Object.entries(namedExports).forEach(function (_ref) {
|
|
851
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
852
|
+
exportName = _ref2[0],
|
|
853
|
+
exported = _ref2[1];
|
|
854
|
+
|
|
855
|
+
if (exportName !== 'default') component[exportName] = exported;
|
|
856
|
+
});module.exports=component;
|