/** * A collection of default build flags for a Stencil project. * * This collection can be found throughout the Stencil codebase, often imported from the `@app-data` module like so: * ```ts * import { BUILD } from '@app-data'; * ``` * and is used to determine if a portion of the output of a Stencil _project_'s compilation step can be eliminated. * * e.g. When `BUILD.allRenderFn` evaluates to `false`, the compiler will eliminate conditional statements like: * ```ts * if (BUILD.allRenderFn) { * // some code that will be eliminated if BUILD.allRenderFn is false * } * ``` * * `@app-data`, the module that `BUILD` is imported from, is an alias for the `@stencil/core/internal/app-data`, and is * partially referenced by {@link STENCIL_APP_DATA_ID}. The `src/compiler/bundle/app-data-plugin.ts` references * `STENCIL_APP_DATA_ID` uses it to replace these defaults with {@link BuildConditionals} that are derived from a * Stencil project's contents (i.e. metadata from the components). This replacement happens at a Stencil project's * compile time. Such code can be found at `src/compiler/app-core/app-data.ts`. */ const BUILD = { allRenderFn: false, cmpDidLoad: true, cmpDidUnload: false, cmpDidUpdate: true, cmpDidRender: true, cmpWillLoad: true, cmpWillUpdate: true, cmpWillRender: true, connectedCallback: true, disconnectedCallback: true, element: true, event: true, hasRenderFn: true, lifecycle: true, hostListener: true, hostListenerTargetWindow: true, hostListenerTargetDocument: true, hostListenerTargetBody: true, hostListenerTargetParent: false, hostListenerTarget: true, member: true, method: true, mode: true, observeAttribute: true, prop: true, propMutable: true, reflect: true, scoped: true, shadowDom: true, slot: true, cssAnnotations: true, state: true, style: true, formAssociated: false, svg: true, updatable: true, vdomAttribute: true, vdomXlink: true, vdomClass: true, vdomFunctional: true, vdomKey: true, vdomListener: true, vdomRef: true, vdomPropOrAttr: true, vdomRender: true, vdomStyle: true, vdomText: true, watchCallback: true, taskQueue: true, hotModuleReplacement: false, isDebug: false, isDev: false, isTesting: false, hydrateServerSide: false, hydrateClientSide: false, lifecycleDOMEvents: false, lazyLoad: false, profile: false, slotRelocation: true, // TODO(STENCIL-914): remove this option when `experimentalSlotFixes` is the default behavior appendChildSlotFix: false, // TODO(STENCIL-914): remove this option when `experimentalSlotFixes` is the default behavior cloneNodeFix: false, hydratedAttribute: false, hydratedClass: true, scriptDataOpts: false, // TODO(STENCIL-914): remove this option when `experimentalSlotFixes` is the default behavior scopedSlotTextContentFix: false, // TODO(STENCIL-854): Remove code related to legacy shadowDomShim field shadowDomShim: false, // TODO(STENCIL-914): remove this option when `experimentalSlotFixes` is the default behavior slotChildNodesFix: false, invisiblePrehydration: true, propBoolean: true, propNumber: true, propString: true, constructableCSS: true, cmpShouldUpdate: true, devTools: false, shadowDelegatesFocus: true, initializeNextTick: false, asyncLoading: false, asyncQueue: false, transformTagName: false, attachStyles: true, // TODO(STENCIL-914): remove this option when `experimentalSlotFixes` is the default behavior experimentalSlotFixes: false, }; /** * Virtual DOM patching algorithm based on Snabbdom by * Simon Friis Vindum (@paldepind) * Licensed under the MIT License * https://github.com/snabbdom/snabbdom/blob/master/LICENSE * * Modified for Stencil's renderer and slot projection */ let scopeId; let contentRef; let hostTagName; let useNativeShadowDom = false; let checkSlotFallbackVisibility = false; let checkSlotRelocate = false; let isSvgMode = false; let renderingRef = null; let queuePending = false; const createTime = (fnName, tagName = '') => { { return () => { return; }; } }; /** * Constant for styles to be globally applied to `slot-fb` elements for pseudo-slot behavior. * * Two cascading rules must be used instead of a `:not()` selector due to Stencil browser * support as of Stencil v4. */ const SLOT_FB_CSS = 'slot-fb{display:contents}slot-fb[hidden]{display:none}'; const XLINK_NS = 'http://www.w3.org/1999/xlink'; /** * Default style mode id */ /** * Reusable empty obj/array * Don't add values to these!! */ const EMPTY_OBJ = {}; /** * Namespaces */ const SVG_NS = 'http://www.w3.org/2000/svg'; const HTML_NS = 'http://www.w3.org/1999/xhtml'; const isDef = (v) => v != null; /** * Check whether a value is a 'complex type', defined here as an object or a * function. * * @param o the value to check * @returns whether it's a complex type or not */ const isComplexType = (o) => { // https://jsperf.com/typeof-fn-object/5 o = typeof o; return o === 'object' || o === 'function'; }; /** * Helper method for querying a `meta` tag that contains a nonce value * out of a DOM's head. * * @param doc The DOM containing the `head` to query against * @returns The content of the meta tag representing the nonce value, or `undefined` if no tag * exists or the tag has no content. */ function queryNonceMetaTagContent(doc) { var _a, _b, _c; return (_c = (_b = (_a = doc.head) === null || _a === void 0 ? void 0 : _a.querySelector('meta[name="csp-nonce"]')) === null || _b === void 0 ? void 0 : _b.getAttribute('content')) !== null && _c !== void 0 ? _c : undefined; } /** * Production h() function based on Preact by * Jason Miller (@developit) * Licensed under the MIT License * https://github.com/developit/preact/blob/master/LICENSE * * Modified for Stencil's compiler and vdom */ // export function h(nodeName: string | d.FunctionalComponent, vnodeData: d.PropsType, child?: d.ChildType): d.VNode; // export function h(nodeName: string | d.FunctionalComponent, vnodeData: d.PropsType, ...children: d.ChildType[]): d.VNode; const h = (nodeName, vnodeData, ...children) => { let child = null; let key = null; let slotName = null; let simple = false; let lastSimple = false; const vNodeChildren = []; const walk = (c) => { for (let i = 0; i < c.length; i++) { child = c[i]; if (Array.isArray(child)) { walk(child); } else if (child != null && typeof child !== 'boolean') { if ((simple = typeof nodeName !== 'function' && !isComplexType(child))) { child = String(child); } if (simple && lastSimple) { // If the previous child was simple (string), we merge both vNodeChildren[vNodeChildren.length - 1].$text$ += child; } else { // Append a new vNode, if it's text, we create a text vNode vNodeChildren.push(simple ? newVNode(null, child) : child); } lastSimple = simple; } } }; walk(children); if (vnodeData) { if (vnodeData.key) { key = vnodeData.key; } if (vnodeData.name) { slotName = vnodeData.name; } // normalize class / className attributes { const classData = vnodeData.className || vnodeData.class; if (classData) { vnodeData.class = typeof classData !== 'object' ? classData : Object.keys(classData) .filter((k) => classData[k]) .join(' '); } } } if (typeof nodeName === 'function') { // nodeName is a functional component return nodeName(vnodeData === null ? {} : vnodeData, vNodeChildren, vdomFnUtils); } const vnode = newVNode(nodeName, null); vnode.$attrs$ = vnodeData; if (vNodeChildren.length > 0) { vnode.$children$ = vNodeChildren; } { vnode.$key$ = key; } { vnode.$name$ = slotName; } return vnode; }; /** * A utility function for creating a virtual DOM node from a tag and some * possible text content. * * @param tag the tag for this element * @param text possible text content for the node * @returns a newly-minted virtual DOM node */ const newVNode = (tag, text) => { const vnode = { $flags$: 0, $tag$: tag, $text$: text, $elm$: null, $children$: null, }; { vnode.$attrs$ = null; } { vnode.$key$ = null; } { vnode.$name$ = null; } return vnode; }; const Host = {}; /** * Check whether a given node is a Host node or not * * @param node the virtual DOM node to check * @returns whether it's a Host node or not */ const isHost = (node) => node && node.$tag$ === Host; /** * Implementation of {@link d.FunctionalUtilities} for Stencil's VDom. * * Note that these functions convert from {@link d.VNode} to * {@link d.ChildNode} to give functional component developers a friendly * interface. */ const vdomFnUtils = { forEach: (children, cb) => children.map(convertToPublic).forEach(cb), map: (children, cb) => children.map(convertToPublic).map(cb).map(convertToPrivate), }; /** * Convert a {@link d.VNode} to a {@link d.ChildNode} in order to present a * friendlier public interface (hence, 'convertToPublic'). * * @param node the virtual DOM node to convert * @returns a converted child node */ const convertToPublic = (node) => ({ vattrs: node.$attrs$, vchildren: node.$children$, vkey: node.$key$, vname: node.$name$, vtag: node.$tag$, vtext: node.$text$, }); /** * Convert a {@link d.ChildNode} back to an equivalent {@link d.VNode} in * order to use the resulting object in the virtual DOM. The initial object was * likely created as part of presenting a public API, so converting it back * involved making it 'private' again (hence, `convertToPrivate`). * * @param node the child node to convert * @returns a converted virtual DOM node */ const convertToPrivate = (node) => { if (typeof node.vtag === 'function') { const vnodeData = Object.assign({}, node.vattrs); if (node.vkey) { vnodeData.key = node.vkey; } if (node.vname) { vnodeData.name = node.vname; } return h(node.vtag, vnodeData, ...(node.vchildren || [])); } const vnode = newVNode(node.vtag, node.vtext); vnode.$attrs$ = node.vattrs; vnode.$children$ = node.vchildren; vnode.$key$ = node.vkey; vnode.$name$ = node.vname; return vnode; }; // Private const computeMode = (elm) => modeResolutionChain.map((h) => h(elm)).find((m) => !!m); /** * Parse a new property value for a given property type. * * While the prop value can reasonably be expected to be of `any` type as far as TypeScript's type checker is concerned, * it is not safe to assume that the string returned by evaluating `typeof propValue` matches: * 1. `any`, the type given to `propValue` in the function signature * 2. the type stored from `propType`. * * This function provides the capability to parse/coerce a property's value to potentially any other JavaScript type. * * Property values represented in TSX preserve their type information. In the example below, the number 0 is passed to * a component. This `propValue` will preserve its type information (`typeof propValue === 'number'`). Note that is * based on the type of the value being passed in, not the type declared of the class member decorated with `@Prop`. * ```tsx * * ``` * * HTML prop values on the other hand, will always a string * * @param propValue the new value to coerce to some type * @param propType the type of the prop, expressed as a binary number * @returns the parsed/coerced value */ const parsePropertyValue = (propValue, propType) => { // ensure this value is of the correct prop type if (propValue != null && !isComplexType(propValue)) { if (propType & 4 /* MEMBER_FLAGS.Boolean */) { // per the HTML spec, any string value means it is a boolean true value // but we'll cheat here and say that the string "false" is the boolean false return propValue === 'false' ? false : propValue === '' || !!propValue; } if (propType & 2 /* MEMBER_FLAGS.Number */) { // force it to be a number return parseFloat(propValue); } if (propType & 1 /* MEMBER_FLAGS.String */) { // could have been passed as a number or boolean // but we still want it as a string return String(propValue); } // redundant return here for better minification return propValue; } // not sure exactly what type we want // so no need to change to a different type return propValue; }; const getElement = (ref) => (ref); const createEvent = (ref, name, flags) => { const elm = getElement(ref); return { emit: (detail) => { return emitEvent(elm, name, { bubbles: !!(flags & 4 /* EVENT_FLAGS.Bubbles */), composed: !!(flags & 2 /* EVENT_FLAGS.Composed */), cancelable: !!(flags & 1 /* EVENT_FLAGS.Cancellable */), detail, }); }, }; }; /** * Helper function to create & dispatch a custom Event on a provided target * @param elm the target of the Event * @param name the name to give the custom Event * @param opts options for configuring a custom Event * @returns the custom Event */ const emitEvent = (elm, name, opts) => { const ev = plt.ce(name, opts); elm.dispatchEvent(ev); return ev; }; const rootAppliedStyles = /*@__PURE__*/ new WeakMap(); const registerStyle = (scopeId, cssText, allowCS) => { let style = styles.get(scopeId); if (supportsConstructableStylesheets && allowCS) { style = (style || new CSSStyleSheet()); if (typeof style === 'string') { style = cssText; } else { style.replaceSync(cssText); } } else { style = cssText; } styles.set(scopeId, style); }; const addStyle = (styleContainerNode, cmpMeta, mode) => { var _a; const scopeId = getScopeId(cmpMeta, mode); const style = styles.get(scopeId); // if an element is NOT connected then getRootNode() will return the wrong root node // so the fallback is to always use the document for the root node in those cases styleContainerNode = styleContainerNode.nodeType === 11 /* NODE_TYPE.DocumentFragment */ ? styleContainerNode : doc$1; if (style) { if (typeof style === 'string') { styleContainerNode = styleContainerNode.head || styleContainerNode; let appliedStyles = rootAppliedStyles.get(styleContainerNode); let styleElm; if (!appliedStyles) { rootAppliedStyles.set(styleContainerNode, (appliedStyles = new Set())); } if (!appliedStyles.has(scopeId)) { { styleElm = doc$1.createElement('style'); styleElm.innerHTML = style; // Apply CSP nonce to the style tag if it exists const nonce = (_a = plt.$nonce$) !== null && _a !== void 0 ? _a : queryNonceMetaTagContent(doc$1); if (nonce != null) { styleElm.setAttribute('nonce', nonce); } styleContainerNode.insertBefore(styleElm, styleContainerNode.querySelector('link')); } // Add styles for `slot-fb` elements if we're using slots outside the Shadow DOM if (cmpMeta.$flags$ & 4 /* CMP_FLAGS.hasSlotRelocation */) { styleElm.innerHTML += SLOT_FB_CSS; } if (appliedStyles) { appliedStyles.add(scopeId); } } } else if (!styleContainerNode.adoptedStyleSheets.includes(style)) { styleContainerNode.adoptedStyleSheets = [...styleContainerNode.adoptedStyleSheets, style]; } } return scopeId; }; const attachStyles = (hostRef) => { const cmpMeta = hostRef.$cmpMeta$; const elm = hostRef.$hostElement$; const flags = cmpMeta.$flags$; const endAttachStyles = createTime('attachStyles', cmpMeta.$tagName$); const scopeId = addStyle(elm.shadowRoot ? elm.shadowRoot : elm.getRootNode(), cmpMeta, hostRef.$modeName$); if (flags & 10 /* CMP_FLAGS.needsScopedEncapsulation */) { // only required when we're NOT using native shadow dom (slot) // or this browser doesn't support native shadow dom // and this host element was NOT created with SSR // let's pick out the inner content for slot projection // create a node to represent where the original // content was first placed, which is useful later on // DOM WRITE!! elm['s-sc'] = scopeId; elm.classList.add(scopeId + '-h'); if (flags & 2 /* CMP_FLAGS.scopedCssEncapsulation */) { elm.classList.add(scopeId + '-s'); } } endAttachStyles(); }; const getScopeId = (cmp, mode) => 'sc-' + (mode && cmp.$flags$ & 32 /* CMP_FLAGS.hasMode */ ? cmp.$tagName$ + '-' + mode : cmp.$tagName$); /** * Production setAccessor() function based on Preact by * Jason Miller (@developit) * Licensed under the MIT License * https://github.com/developit/preact/blob/master/LICENSE * * Modified for Stencil's compiler and vdom */ /** * When running a VDom render set properties present on a VDom node onto the * corresponding HTML element. * * Note that this function has special functionality for the `class`, * `style`, `key`, and `ref` attributes, as well as event handlers (like * `onClick`, etc). All others are just passed through as-is. * * @param elm the HTMLElement onto which attributes should be set * @param memberName the name of the attribute to set * @param oldValue the old value for the attribute * @param newValue the new value for the attribute * @param isSvg whether we're in an svg context or not * @param flags bitflags for Vdom variables */ const setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags) => { if (oldValue !== newValue) { let isProp = isMemberInElement(elm, memberName); let ln = memberName.toLowerCase(); if (memberName === 'class') { const classList = elm.classList; const oldClasses = parseClassList(oldValue); const newClasses = parseClassList(newValue); classList.remove(...oldClasses.filter((c) => c && !newClasses.includes(c))); classList.add(...newClasses.filter((c) => c && !oldClasses.includes(c))); } else if (memberName === 'style') { // update style attribute, css properties and values { for (const prop in oldValue) { if (!newValue || newValue[prop] == null) { if (prop.includes('-')) { elm.style.removeProperty(prop); } else { elm.style[prop] = ''; } } } } for (const prop in newValue) { if (!oldValue || newValue[prop] !== oldValue[prop]) { if (prop.includes('-')) { elm.style.setProperty(prop, newValue[prop]); } else { elm.style[prop] = newValue[prop]; } } } } else if (memberName === 'key') ; else if (memberName === 'ref') { // minifier will clean this up if (newValue) { newValue(elm); } } else if ((!elm.__lookupSetter__(memberName)) && memberName[0] === 'o' && memberName[1] === 'n') { // Event Handlers // so if the member name starts with "on" and the 3rd characters is // a capital letter, and it's not already a member on the element, // then we're assuming it's an event listener if (memberName[2] === '-') { // on- prefixed events // allows to be explicit about the dom event to listen without any magic // under the hood: // // listens for "click" // // listens for "Click" // // listens for "ionChange" // // listens for "EVENTS" memberName = memberName.slice(3); } else if (isMemberInElement(win, ln)) { // standard event // the JSX attribute could have been "onMouseOver" and the // member name "onmouseover" is on the window's prototype // so let's add the listener "mouseover", which is all lowercased memberName = ln.slice(2); } else { // custom event // the JSX attribute could have been "onMyCustomEvent" // so let's trim off the "on" prefix and lowercase the first character // and add the listener "myCustomEvent" // except for the first character, we keep the event name case memberName = ln[2] + memberName.slice(3); } if (oldValue || newValue) { // Need to account for "capture" events. // If the event name ends with "Capture", we'll update the name to remove // the "Capture" suffix and make sure the event listener is setup to handle the capture event. const capture = memberName.endsWith(CAPTURE_EVENT_SUFFIX); // Make sure we only replace the last instance of "Capture" memberName = memberName.replace(CAPTURE_EVENT_REGEX, ''); if (oldValue) { plt.rel(elm, memberName, oldValue, capture); } if (newValue) { plt.ael(elm, memberName, newValue, capture); } } } else { // Set property if it exists and it's not a SVG const isComplex = isComplexType(newValue); if ((isProp || (isComplex && newValue !== null)) && !isSvg) { try { if (!elm.tagName.includes('-')) { const n = newValue == null ? '' : newValue; // Workaround for Safari, moving the caret when re-assigning the same valued if (memberName === 'list') { isProp = false; } else if (oldValue == null || elm[memberName] != n) { elm[memberName] = n; } } else { elm[memberName] = newValue; } } catch (e) { /** * in case someone tries to set a read-only property, e.g. "namespaceURI", we just ignore it */ } } /** * Need to manually update attribute if: * - memberName is not an attribute * - if we are rendering the host element in order to reflect attribute * - if it's a SVG, since properties might not work in * - if the newValue is null/undefined or 'false'. */ let xlink = false; { if (ln !== (ln = ln.replace(/^xlink\:?/, ''))) { memberName = ln; xlink = true; } } if (newValue == null || newValue === false) { if (newValue !== false || elm.getAttribute(memberName) === '') { if (xlink) { elm.removeAttributeNS(XLINK_NS, memberName); } else { elm.removeAttribute(memberName); } } } else if ((!isProp || flags & 4 /* VNODE_FLAGS.isHost */ || isSvg) && !isComplex) { newValue = newValue === true ? '' : newValue; if (xlink) { elm.setAttributeNS(XLINK_NS, memberName, newValue); } else { elm.setAttribute(memberName, newValue); } } } } }; const parseClassListRegex = /\s/; /** * Parsed a string of classnames into an array * @param value className string, e.g. "foo bar baz" * @returns list of classes, e.g. ["foo", "bar", "baz"] */ const parseClassList = (value) => (!value ? [] : value.split(parseClassListRegex)); const CAPTURE_EVENT_SUFFIX = 'Capture'; const CAPTURE_EVENT_REGEX = new RegExp(CAPTURE_EVENT_SUFFIX + '$'); const updateElement = (oldVnode, newVnode, isSvgMode, memberName) => { // if the element passed in is a shadow root, which is a document fragment // then we want to be adding attrs/props to the shadow root's "host" element // if it's not a shadow root, then we add attrs/props to the same element const elm = newVnode.$elm$.nodeType === 11 /* NODE_TYPE.DocumentFragment */ && newVnode.$elm$.host ? newVnode.$elm$.host : newVnode.$elm$; const oldVnodeAttrs = (oldVnode && oldVnode.$attrs$) || EMPTY_OBJ; const newVnodeAttrs = newVnode.$attrs$ || EMPTY_OBJ; { // remove attributes no longer present on the vnode by setting them to undefined for (memberName in oldVnodeAttrs) { if (!(memberName in newVnodeAttrs)) { setAccessor(elm, memberName, oldVnodeAttrs[memberName], undefined, isSvgMode, newVnode.$flags$); } } } // add new & update changed attributes for (memberName in newVnodeAttrs) { setAccessor(elm, memberName, oldVnodeAttrs[memberName], newVnodeAttrs[memberName], isSvgMode, newVnode.$flags$); } }; /** * Create a DOM Node corresponding to one of the children of a given VNode. * * @param oldParentVNode the parent VNode from the previous render * @param newParentVNode the parent VNode from the current render * @param childIndex the index of the VNode, in the _new_ parent node's * children, for which we will create a new DOM node * @param parentElm the parent DOM node which our new node will be a child of * @returns the newly created node */ const createElm = (oldParentVNode, newParentVNode, childIndex, parentElm) => { var _a; // tslint:disable-next-line: prefer-const const newVNode = newParentVNode.$children$[childIndex]; let i = 0; let elm; let childNode; let oldVNode; if (!useNativeShadowDom) { // remember for later we need to check to relocate nodes checkSlotRelocate = true; if (newVNode.$tag$ === 'slot') { if (scopeId) { // scoped css needs to add its scoped id to the parent element parentElm.classList.add(scopeId + '-s'); } newVNode.$flags$ |= newVNode.$children$ ? // slot element has fallback content 2 /* VNODE_FLAGS.isSlotFallback */ : // slot element does not have fallback content 1 /* VNODE_FLAGS.isSlotReference */; } } if (newVNode.$text$ !== null) { // create text node elm = newVNode.$elm$ = doc$1.createTextNode(newVNode.$text$); } else if (newVNode.$flags$ & 1 /* VNODE_FLAGS.isSlotReference */) { // create a slot reference node elm = newVNode.$elm$ = doc$1.createTextNode(''); } else { if (!isSvgMode) { isSvgMode = newVNode.$tag$ === 'svg'; } // create element elm = newVNode.$elm$ = (doc$1.createElementNS(isSvgMode ? SVG_NS : HTML_NS, newVNode.$flags$ & 2 /* VNODE_FLAGS.isSlotFallback */ ? 'slot-fb' : newVNode.$tag$) ); if (isSvgMode && newVNode.$tag$ === 'foreignObject') { isSvgMode = false; } // add css classes, attrs, props, listeners, etc. { updateElement(null, newVNode, isSvgMode); } if (isDef(scopeId) && elm['s-si'] !== scopeId) { // if there is a scopeId and this is the initial render // then let's add the scopeId as a css class elm.classList.add((elm['s-si'] = scopeId)); } if (newVNode.$children$) { for (i = 0; i < newVNode.$children$.length; ++i) { // create the node childNode = createElm(oldParentVNode, newVNode, i, elm); // return node could have been null if (childNode) { // append our new node elm.appendChild(childNode); } } } { if (newVNode.$tag$ === 'svg') { // Only reset the SVG context when we're exiting element isSvgMode = false; } else if (elm.tagName === 'foreignObject') { // Reenter SVG context when we're exiting element isSvgMode = true; } } } { elm['s-hn'] = hostTagName; if (newVNode.$flags$ & (2 /* VNODE_FLAGS.isSlotFallback */ | 1 /* VNODE_FLAGS.isSlotReference */)) { // remember the content reference comment elm['s-sr'] = true; // Persist the name of the slot that this slot was going to be projected into. elm['s-fs'] = (_a = newVNode.$attrs$) === null || _a === void 0 ? void 0 : _a.slot; // remember the content reference comment elm['s-cr'] = contentRef; // remember the slot name, or empty string for default slot elm['s-sn'] = newVNode.$name$ || ''; // check if we've got an old vnode for this slot oldVNode = oldParentVNode && oldParentVNode.$children$ && oldParentVNode.$children$[childIndex]; if (oldVNode && oldVNode.$tag$ === newVNode.$tag$ && oldParentVNode.$elm$) { // we've got an old slot vnode and the wrapper is being replaced // so let's move the old slot content back to it's original location putBackInOriginalLocation(oldParentVNode.$elm$, false); } } } return elm; }; const putBackInOriginalLocation = (parentElm, recursive) => { var _a; plt.$flags$ |= 1 /* PLATFORM_FLAGS.isTmpDisconnected */; const oldSlotChildNodes = parentElm.childNodes; for (let i = oldSlotChildNodes.length - 1; i >= 0; i--) { const childNode = oldSlotChildNodes[i]; if (childNode['s-hn'] !== hostTagName && childNode['s-ol']) { // // this child node in the old element is from another component // // remove this node from the old slot's parent // childNode.remove(); // and relocate it back to it's original location parentReferenceNode(childNode).insertBefore(childNode, referenceNode(childNode)); // remove the old original location comment entirely // later on the patch function will know what to do // and move this to the correct spot if need be childNode['s-ol'].remove(); childNode['s-ol'] = undefined; // Reset so we can correctly move the node around again. childNode['s-sh'] = undefined; // When putting an element node back in its original location, // we need to reset the `slot` attribute back to the value it originally had // so we can correctly relocate it again in the future if (childNode.nodeType === 1 /* NODE_TYPE.ElementNode */) { childNode.setAttribute('slot', (_a = childNode['s-sn']) !== null && _a !== void 0 ? _a : ''); } checkSlotRelocate = true; } if (recursive) { putBackInOriginalLocation(childNode, recursive); } } plt.$flags$ &= ~1 /* PLATFORM_FLAGS.isTmpDisconnected */; }; /** * Create DOM nodes corresponding to a list of {@link d.Vnode} objects and * add them to the DOM in the appropriate place. * * @param parentElm the DOM node which should be used as a parent for the new * DOM nodes * @param before a child of the `parentElm` which the new children should be * inserted before (optional) * @param parentVNode the parent virtual DOM node * @param vnodes the new child virtual DOM nodes to produce DOM nodes for * @param startIdx the index in the child virtual DOM nodes at which to start * creating DOM nodes (inclusive) * @param endIdx the index in the child virtual DOM nodes at which to stop * creating DOM nodes (inclusive) */ const addVnodes = (parentElm, before, parentVNode, vnodes, startIdx, endIdx) => { let containerElm = ((parentElm['s-cr'] && parentElm['s-cr'].parentNode) || parentElm); let childNode; if (containerElm.shadowRoot && containerElm.tagName === hostTagName) { containerElm = containerElm.shadowRoot; } for (; startIdx <= endIdx; ++startIdx) { if (vnodes[startIdx]) { childNode = createElm(null, parentVNode, startIdx, parentElm); if (childNode) { vnodes[startIdx].$elm$ = childNode; containerElm.insertBefore(childNode, referenceNode(before) ); } } } }; /** * Remove the DOM elements corresponding to a list of {@link d.VNode} objects. * This can be used to, for instance, clean up after a list of children which * should no longer be shown. * * This function also handles some of Stencil's slot relocation logic. * * @param vnodes a list of virtual DOM nodes to remove * @param startIdx the index at which to start removing nodes (inclusive) * @param endIdx the index at which to stop removing nodes (inclusive) */ const removeVnodes = (vnodes, startIdx, endIdx) => { for (let index = startIdx; index <= endIdx; ++index) { const vnode = vnodes[index]; if (vnode) { const elm = vnode.$elm$; nullifyVNodeRefs(vnode); if (elm) { { // we're removing this element // so it's possible we need to show slot fallback content now checkSlotFallbackVisibility = true; if (elm['s-ol']) { // remove the original location comment elm['s-ol'].remove(); } else { // it's possible that child nodes of the node // that's being removed are slot nodes putBackInOriginalLocation(elm, true); } } // remove the vnode's element from the dom elm.remove(); } } } }; /** * Reconcile the children of a new VNode with the children of an old VNode by * traversing the two collections of children, identifying nodes that are * conserved or changed, calling out to `patch` to make any necessary * updates to the DOM, and rearranging DOM nodes as needed. * * The algorithm for reconciling children works by analyzing two 'windows' onto * the two arrays of children (`oldCh` and `newCh`). We keep track of the * 'windows' by storing start and end indices and references to the * corresponding array entries. Initially the two 'windows' are basically equal * to the entire array, but we progressively narrow the windows until there are * no children left to update by doing the following: * * 1. Skip any `null` entries at the beginning or end of the two arrays, so * that if we have an initial array like the following we'll end up dealing * only with a window bounded by the highlighted elements: * * [null, null, VNode1 , ... , VNode2, null, null] * ^^^^^^ ^^^^^^ * * 2. Check to see if the elements at the head and tail positions are equal * across the windows. This will basically detect elements which haven't * been added, removed, or changed position, i.e. if you had the following * VNode elements (represented as HTML): * * oldVNode: `

HEY

` * newVNode: `

THERE

` * * Then when comparing the children of the `
` tag we check the equality * of the VNodes corresponding to the `

` tags and, since they are the * same tag in the same position, we'd be able to avoid completely * re-rendering the subtree under them with a new DOM element and would just * call out to `patch` to handle reconciling their children and so on. * * 3. Check, for both windows, to see if the element at the beginning of the * window corresponds to the element at the end of the other window. This is * a heuristic which will let us identify _some_ situations in which * elements have changed position, for instance it _should_ detect that the * children nodes themselves have not changed but merely moved in the * following example: * * oldVNode: `

` * newVNode: `
` * * If we find cases like this then we also need to move the concrete DOM * elements corresponding to the moved children to write the re-order to the * DOM. * * 4. Finally, if VNodes have the `key` attribute set on them we check for any * nodes in the old children which have the same key as the first element in * our window on the new children. If we find such a node we handle calling * out to `patch`, moving relevant DOM nodes, and so on, in accordance with * what we find. * * Finally, once we've narrowed our 'windows' to the point that either of them * collapse (i.e. they have length 0) we then handle any remaining VNode * insertion or deletion that needs to happen to get a DOM state that correctly * reflects the new child VNodes. If, for instance, after our window on the old * children has collapsed we still have more nodes on the new children that * we haven't dealt with yet then we need to add them, or if the new children * collapse but we still have unhandled _old_ children then we need to make * sure the corresponding DOM nodes are removed. * * @param parentElm the node into which the parent VNode is rendered * @param oldCh the old children of the parent node * @param newVNode the new VNode which will replace the parent * @param newCh the new children of the parent node */ const updateChildren = (parentElm, oldCh, newVNode, newCh) => { let oldStartIdx = 0; let newStartIdx = 0; let idxInOld = 0; let i = 0; let oldEndIdx = oldCh.length - 1; let oldStartVnode = oldCh[0]; let oldEndVnode = oldCh[oldEndIdx]; let newEndIdx = newCh.length - 1; let newStartVnode = newCh[0]; let newEndVnode = newCh[newEndIdx]; let node; let elmToMove; while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) { if (oldStartVnode == null) { // VNode might have been moved left oldStartVnode = oldCh[++oldStartIdx]; } else if (oldEndVnode == null) { oldEndVnode = oldCh[--oldEndIdx]; } else if (newStartVnode == null) { newStartVnode = newCh[++newStartIdx]; } else if (newEndVnode == null) { newEndVnode = newCh[--newEndIdx]; } else if (isSameVnode(oldStartVnode, newStartVnode)) { // if the start nodes are the same then we should patch the new VNode // onto the old one, and increment our `newStartIdx` and `oldStartIdx` // indices to reflect that. We don't need to move any DOM Nodes around // since things are matched up in order. patch(oldStartVnode, newStartVnode); oldStartVnode = oldCh[++oldStartIdx]; newStartVnode = newCh[++newStartIdx]; } else if (isSameVnode(oldEndVnode, newEndVnode)) { // likewise, if the end nodes are the same we patch new onto old and // decrement our end indices, and also likewise in this case we don't // need to move any DOM Nodes. patch(oldEndVnode, newEndVnode); oldEndVnode = oldCh[--oldEndIdx]; newEndVnode = newCh[--newEndIdx]; } else if (isSameVnode(oldStartVnode, newEndVnode)) { // case: "Vnode moved right" // // We've found that the last node in our window on the new children is // the same VNode as the _first_ node in our window on the old children // we're dealing with now. Visually, this is the layout of these two // nodes: // // newCh: [..., newStartVnode , ... , newEndVnode , ...] // ^^^^^^^^^^^ // oldCh: [..., oldStartVnode , ... , oldEndVnode , ...] // ^^^^^^^^^^^^^ // // In this situation we need to patch `newEndVnode` onto `oldStartVnode` // and move the DOM element for `oldStartVnode`. if ((oldStartVnode.$tag$ === 'slot' || newEndVnode.$tag$ === 'slot')) { putBackInOriginalLocation(oldStartVnode.$elm$.parentNode, false); } patch(oldStartVnode, newEndVnode); // We need to move the element for `oldStartVnode` into a position which // will be appropriate for `newEndVnode`. For this we can use // `.insertBefore` and `oldEndVnode.$elm$.nextSibling`. If there is a // sibling for `oldEndVnode.$elm$` then we want to move the DOM node for // `oldStartVnode` between `oldEndVnode` and it's sibling, like so: // // // // // // // // ``` // In this case if we do not un-shadow here and use the value of the shadowing property, attributeChangedCallback // will be called with `newValue = "some-value"` and will set the shadowed property (this.someAttribute = "another-value") // to the value that was set inline i.e. "some-value" from above example. When // the connectedCallback attempts to un-shadow it will use "some-value" as the initial value rather than "another-value" // // The case where the attribute was NOT set inline but was not set programmatically shall be handled/un-shadowed // by connectedCallback as this attributeChangedCallback will not fire. // // https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties // // TODO(STENCIL-16) we should think about whether or not we actually want to be reflecting the attributes to // properties here given that this goes against best practices outlined here // https://developers.google.com/web/fundamentals/web-components/best-practices#avoid-reentrancy if (this.hasOwnProperty(propName)) { newValue = this[propName]; delete this[propName]; } else if (prototype.hasOwnProperty(propName) && typeof this[propName] === 'number' && this[propName] == newValue) { // if the propName exists on the prototype of `Cstr`, this update may be a result of Stencil using native // APIs to reflect props as attributes. Calls to `setAttribute(someElement, propName)` will result in // `propName` to be converted to a `DOMString`, which may not be what we want for other primitive props. return; } else if (propName == null) { // At this point we should know this is not a "member", so we can treat it like watching an attribute // on a vanilla web component const hostRef = getHostRef(this); const flags = hostRef === null || hostRef === void 0 ? void 0 : hostRef.$flags$; // We only want to trigger the callback(s) if: // 1. The instance is ready // 2. The watchers are ready // 3. The value has changed if (flags && !(flags & 8 /* HOST_FLAGS.isConstructingInstance */) && flags & 128 /* HOST_FLAGS.isWatchReady */ && newValue !== oldValue) { const elm = this; const instance = elm; const entry = (_a = cmpMeta.$watchers$) === null || _a === void 0 ? void 0 : _a[attrName]; entry === null || entry === void 0 ? void 0 : entry.forEach((callbackName) => { if (instance[callbackName] != null) { instance[callbackName].call(instance, newValue, oldValue, attrName); } }); } return; } this[propName] = newValue === null && typeof this[propName] === 'boolean' ? false : newValue; }); }; // Create an array of attributes to observe // This list in comprised of all strings used within a `@Watch()` decorator // on a component as well as any Stencil-specific "members" (`@Prop()`s and `@State()`s). // As such, there is no way to guarantee type-safety here that a user hasn't entered // an invalid attribute. Cstr.observedAttributes = Array.from(new Set([ ...Object.keys((_a = cmpMeta.$watchers$) !== null && _a !== void 0 ? _a : {}), ...members .filter(([_, m]) => m[0] & 15 /* MEMBER_FLAGS.HasAttribute */) .map(([propName, m]) => { var _a; const attrName = m[1] || propName; attrNameToPropName.set(attrName, propName); if (m[0] & 512 /* MEMBER_FLAGS.ReflectAttr */) { (_a = cmpMeta.$attrsToReflect$) === null || _a === void 0 ? void 0 : _a.push([propName, attrName]); } return attrName; }), ])); } } return Cstr; }; /** * Initialize a Stencil component given a reference to its host element, its * runtime bookkeeping data structure, runtime metadata about the component, * and (optionally) an HMR version ID. * * @param elm a host element * @param hostRef the element's runtime bookkeeping object * @param cmpMeta runtime metadata for the Stencil component * @param hmrVersionId an (optional) HMR version ID */ const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId) => { let Cstr; // initializeComponent if ((hostRef.$flags$ & 32 /* HOST_FLAGS.hasInitializedComponent */) === 0) { // Let the runtime know that the component has been initialized hostRef.$flags$ |= 32 /* HOST_FLAGS.hasInitializedComponent */; { // sync constructor component Cstr = elm.constructor; // wait for the CustomElementRegistry to mark the component as ready before setting `isWatchReady`. Otherwise, // watchers may fire prematurely if `customElements.get()`/`customElements.whenDefined()` resolves _before_ // Stencil has completed instantiating the component. customElements.whenDefined(cmpMeta.$tagName$).then(() => (hostRef.$flags$ |= 128 /* HOST_FLAGS.isWatchReady */)); } if (Cstr.style) { // this component has styles but we haven't registered them yet let style = Cstr.style; if (typeof style !== 'string') { style = style[(hostRef.$modeName$ = computeMode(elm))]; } const scopeId = getScopeId(cmpMeta, hostRef.$modeName$); if (!styles.has(scopeId)) { const endRegisterStyles = createTime('registerStyles', cmpMeta.$tagName$); registerStyle(scopeId, style, !!(cmpMeta.$flags$ & 1 /* CMP_FLAGS.shadowDomEncapsulation */)); endRegisterStyles(); } } } // we've successfully created a lazy instance hostRef.$ancestorComponent$; const schedule = () => scheduleUpdate(hostRef, true); { schedule(); } }; const fireConnectedCallback = (instance) => { }; const connectedCallback = (elm) => { if ((plt.$flags$ & 1 /* PLATFORM_FLAGS.isTmpDisconnected */) === 0) { const hostRef = getHostRef(elm); const cmpMeta = hostRef.$cmpMeta$; const endConnected = createTime('connectedCallback', cmpMeta.$tagName$); if (!(hostRef.$flags$ & 1 /* HOST_FLAGS.hasConnected */)) { // first time this component has connected hostRef.$flags$ |= 1 /* HOST_FLAGS.hasConnected */; { // initUpdate // if the slot polyfill is required we'll need to put some nodes // in here to act as original content anchors as we move nodes around // host element has been connected to the DOM if ((// TODO(STENCIL-854): Remove code related to legacy shadowDomShim field cmpMeta.$flags$ & (4 /* CMP_FLAGS.hasSlotRelocation */ | 8 /* CMP_FLAGS.needsShadowDomShim */))) { setContentReference(elm); } } // Lazy properties // https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties if (cmpMeta.$members$) { Object.entries(cmpMeta.$members$).map(([memberName, [memberFlags]]) => { if (memberFlags & 31 /* MEMBER_FLAGS.Prop */ && elm.hasOwnProperty(memberName)) { const value = elm[memberName]; delete elm[memberName]; elm[memberName] = value; } }); } { initializeComponent(elm, hostRef, cmpMeta); } } else { // not the first time this has connected // reattach any event listeners to the host // since they would have been removed when disconnected addHostEventListeners(elm, hostRef, cmpMeta.$listeners$); // fire off connectedCallback() on component instance if (hostRef === null || hostRef === void 0 ? void 0 : hostRef.$lazyInstance$) { fireConnectedCallback(hostRef.$lazyInstance$); } else if (hostRef === null || hostRef === void 0 ? void 0 : hostRef.$onReadyPromise$) { hostRef.$onReadyPromise$.then(() => fireConnectedCallback(hostRef.$lazyInstance$)); } } endConnected(); } }; const setContentReference = (elm) => { // only required when we're NOT using native shadow dom (slot) // or this browser doesn't support native shadow dom // and this host element was NOT created with SSR // let's pick out the inner content for slot projection // create a node to represent where the original // content was first placed, which is useful later on const contentRefElm = (elm['s-cr'] = doc$1.createComment('')); contentRefElm['s-cn'] = true; elm.insertBefore(contentRefElm, elm.firstChild); }; const disconnectedCallback = async (elm) => { if ((plt.$flags$ & 1 /* PLATFORM_FLAGS.isTmpDisconnected */) === 0) { const hostRef = getHostRef(elm); { if (hostRef.$rmListeners$) { hostRef.$rmListeners$.map((rmListener) => rmListener()); hostRef.$rmListeners$ = undefined; } } } }; const proxyCustomElement = (Cstr, compactMeta) => { const cmpMeta = { $flags$: compactMeta[0], $tagName$: compactMeta[1], }; { cmpMeta.$members$ = compactMeta[2]; } { cmpMeta.$listeners$ = compactMeta[3]; } { cmpMeta.$watchers$ = Cstr.$watchers$; } { cmpMeta.$attrsToReflect$ = []; } const originalConnectedCallback = Cstr.prototype.connectedCallback; const originalDisconnectedCallback = Cstr.prototype.disconnectedCallback; Object.assign(Cstr.prototype, { __registerHost() { registerHost(this, cmpMeta); }, connectedCallback() { connectedCallback(this); if (originalConnectedCallback) { originalConnectedCallback.call(this); } }, disconnectedCallback() { disconnectedCallback(this); if (originalDisconnectedCallback) { originalDisconnectedCallback.call(this); } }, __attachShadow() { { { this.attachShadow({ mode: 'open', delegatesFocus: !!(cmpMeta.$flags$ & 16 /* CMP_FLAGS.shadowDelegatesFocus */), }); } } }, }); Cstr.is = cmpMeta.$tagName$; return proxyComponent(Cstr, cmpMeta); }; const addHostEventListeners = (elm, hostRef, listeners, attachParentListeners) => { if (listeners) { listeners.map(([flags, name, method]) => { const target = getHostListenerTarget(elm, flags) ; const handler = hostListenerProxy(hostRef, method); const opts = hostListenerOpts(flags); plt.ael(target, name, handler, opts); (hostRef.$rmListeners$ = hostRef.$rmListeners$ || []).push(() => plt.rel(target, name, handler, opts)); }); } }; const hostListenerProxy = (hostRef, methodName) => (ev) => { try { if (BUILD.lazyLoad) ; else { hostRef.$hostElement$[methodName](ev); } } catch (e) { consoleError(e); } }; const getHostListenerTarget = (elm, flags) => { if (flags & 4 /* LISTENER_FLAGS.TargetDocument */) return doc$1; if (flags & 8 /* LISTENER_FLAGS.TargetWindow */) return win; if (flags & 16 /* LISTENER_FLAGS.TargetBody */) return doc$1.body; return elm; }; // prettier-ignore const hostListenerOpts = (flags) => supportsListenerOptions ? ({ passive: (flags & 1 /* LISTENER_FLAGS.Passive */) !== 0, capture: (flags & 2 /* LISTENER_FLAGS.Capture */) !== 0, }) : (flags & 2 /* LISTENER_FLAGS.Capture */) !== 0; /** * A WeakMap mapping runtime component references to their corresponding host reference * instances. */ const hostRefs = /*@__PURE__*/ new WeakMap(); /** * Given a {@link d.RuntimeRef} retrieve the corresponding {@link d.HostRef} * * @param ref the runtime ref of interest * @returns the Host reference (if found) or undefined */ const getHostRef = (ref) => hostRefs.get(ref); /** * Register a host element for a Stencil component, setting up various metadata * and callbacks based on {@link BUILD} flags as well as the component's runtime * metadata. * * @param hostElement the host element to register * @param cmpMeta runtime metadata for that component * @returns a reference to the host ref WeakMap */ const registerHost = (hostElement, cmpMeta) => { const hostRef = { $flags$: 0, $hostElement$: hostElement, $cmpMeta$: cmpMeta, $instanceValues$: new Map(), }; addHostEventListeners(hostElement, hostRef, cmpMeta.$listeners$); return hostRefs.set(hostElement, hostRef); }; const isMemberInElement = (elm, memberName) => memberName in elm; const consoleError = (e, el) => (0, console.error)(e, el); const styles = /*@__PURE__*/ new Map(); const modeResolutionChain = []; const win = typeof window !== 'undefined' ? window : {}; const doc$1 = win.document || { head: {} }; const H = (win.HTMLElement || class { }); const plt = { $flags$: 0, $resourcesUrl$: '', jmp: (h) => h(), raf: (h) => requestAnimationFrame(h), ael: (el, eventName, listener, opts) => el.addEventListener(eventName, listener, opts), rel: (el, eventName, listener, opts) => el.removeEventListener(eventName, listener, opts), ce: (eventName, opts) => new CustomEvent(eventName, opts), }; const supportsListenerOptions = /*@__PURE__*/ (() => { let supportsListenerOptions = false; try { doc$1.addEventListener('e', null, Object.defineProperty({}, 'passive', { get() { supportsListenerOptions = true; }, })); } catch (e) { } return supportsListenerOptions; })(); const promiseResolve = (v) => Promise.resolve(v); const supportsConstructableStylesheets = /*@__PURE__*/ (() => { try { new CSSStyleSheet(); return typeof new CSSStyleSheet().replaceSync === 'function'; } catch (e) { } return false; })() ; const queueDomReads = []; const queueDomWrites = []; const queueTask = (queue, write) => (cb) => { queue.push(cb); if (!queuePending) { queuePending = true; if (write && plt.$flags$ & 4 /* PLATFORM_FLAGS.queueSync */) { nextTick(flush); } else { plt.raf(flush); } } }; const consume = (queue) => { for (let i = 0; i < queue.length; i++) { try { queue[i](performance.now()); } catch (e) { consoleError(e); } } queue.length = 0; }; const flush = () => { // always force a bunch of medium callbacks to run, but still have // a throttle on how many can run in a certain time // DOM READS!!! consume(queueDomReads); // DOM WRITES!!! { consume(queueDomWrites); if ((queuePending = queueDomReads.length > 0)) { // still more to do yet, but we've run out of time // let's let this thing cool off and try again in the next tick plt.raf(flush); } } }; const nextTick = (cb) => promiseResolve().then(cb); const writeTask = /*@__PURE__*/ queueTask(queueDomWrites, true); const filePreviewCss = ":host{display:block;font-size:13px}img,video{max-width:100%;margin-top:10px}"; const FilePreview$1 = /*@__PURE__*/ proxyCustomElement(class FilePreview extends H { constructor() { super(); this.__registerHost(); this.__attachShadow(); this.src = undefined; this.filetype = undefined; } render() { return (h(Host, { class: this.computeClass() }, this.isImage() && h("img", { src: this.src }), this.isVideo() && h("video", { src: this.src, onClick: toggle }), this.isOther() && "This file does not offer a preview", h("slot", null))); } computeClass() { if (this.isImage()) return "image"; if (this.isVideo()) return "video"; return "other"; } isImage() { return this.filetype == "image"; } isVideo() { return this.filetype == "video"; } isOther() { return !this.isImage() && !this.isVideo(); } static get style() { return filePreviewCss; } }, [1, "file-preview", { "src": [513], "filetype": [513] }]); const toggle = function () { this.paused ? this.play() : this.pause(); return false; }; const progressBarCss = ":host{display:block;position:relative;padding:0 20px;border:1px solid rgba(0, 0, 0, 0.3);border-radius:3px;line-height:2;flex:1 0;box-sizing:border-box;text-align:left;font-size:13px}.bar{position:absolute;top:0;left:0;bottom:0;background:rgba(57, 137, 39, 1);transition:width 120ms ease-out, opacity 60ms 60ms ease-in;transform:translate3d(0, 0, 0)}.content{position:relative;color:#fff;font-size:1em}"; const ProgressBar$1 = /*@__PURE__*/ proxyCustomElement(class ProgressBar extends H { constructor() { super(); this.__registerHost(); this.__attachShadow(); this.percent = 0; } render() { return (h(Host, null, h("div", { class: "bar", style: { width: `${this.percent}%` } }), h("span", { class: "content" }, h("slot", null)))); } static get style() { return progressBarCss; } }, [1, "progress-bar", { "percent": [514] }]); var sparkMd5 = { exports: {} }; (function(module, exports) { (function(factory) { { module.exports = factory(); } })((function(undefined$1) { var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ]; function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a += (b & c | ~b & d) + k[0] - 680876936 | 0; a = (a << 7 | a >>> 25) + b | 0; d += (a & b | ~a & c) + k[1] - 389564586 | 0; d = (d << 12 | d >>> 20) + a | 0; c += (d & a | ~d & b) + k[2] + 606105819 | 0; c = (c << 17 | c >>> 15) + d | 0; b += (c & d | ~c & a) + k[3] - 1044525330 | 0; b = (b << 22 | b >>> 10) + c | 0; a += (b & c | ~b & d) + k[4] - 176418897 | 0; a = (a << 7 | a >>> 25) + b | 0; d += (a & b | ~a & c) + k[5] + 1200080426 | 0; d = (d << 12 | d >>> 20) + a | 0; c += (d & a | ~d & b) + k[6] - 1473231341 | 0; c = (c << 17 | c >>> 15) + d | 0; b += (c & d | ~c & a) + k[7] - 45705983 | 0; b = (b << 22 | b >>> 10) + c | 0; a += (b & c | ~b & d) + k[8] + 1770035416 | 0; a = (a << 7 | a >>> 25) + b | 0; d += (a & b | ~a & c) + k[9] - 1958414417 | 0; d = (d << 12 | d >>> 20) + a | 0; c += (d & a | ~d & b) + k[10] - 42063 | 0; c = (c << 17 | c >>> 15) + d | 0; b += (c & d | ~c & a) + k[11] - 1990404162 | 0; b = (b << 22 | b >>> 10) + c | 0; a += (b & c | ~b & d) + k[12] + 1804603682 | 0; a = (a << 7 | a >>> 25) + b | 0; d += (a & b | ~a & c) + k[13] - 40341101 | 0; d = (d << 12 | d >>> 20) + a | 0; c += (d & a | ~d & b) + k[14] - 1502002290 | 0; c = (c << 17 | c >>> 15) + d | 0; b += (c & d | ~c & a) + k[15] + 1236535329 | 0; b = (b << 22 | b >>> 10) + c | 0; a += (b & d | c & ~d) + k[1] - 165796510 | 0; a = (a << 5 | a >>> 27) + b | 0; d += (a & c | b & ~c) + k[6] - 1069501632 | 0; d = (d << 9 | d >>> 23) + a | 0; c += (d & b | a & ~b) + k[11] + 643717713 | 0; c = (c << 14 | c >>> 18) + d | 0; b += (c & a | d & ~a) + k[0] - 373897302 | 0; b = (b << 20 | b >>> 12) + c | 0; a += (b & d | c & ~d) + k[5] - 701558691 | 0; a = (a << 5 | a >>> 27) + b | 0; d += (a & c | b & ~c) + k[10] + 38016083 | 0; d = (d << 9 | d >>> 23) + a | 0; c += (d & b | a & ~b) + k[15] - 660478335 | 0; c = (c << 14 | c >>> 18) + d | 0; b += (c & a | d & ~a) + k[4] - 405537848 | 0; b = (b << 20 | b >>> 12) + c | 0; a += (b & d | c & ~d) + k[9] + 568446438 | 0; a = (a << 5 | a >>> 27) + b | 0; d += (a & c | b & ~c) + k[14] - 1019803690 | 0; d = (d << 9 | d >>> 23) + a | 0; c += (d & b | a & ~b) + k[3] - 187363961 | 0; c = (c << 14 | c >>> 18) + d | 0; b += (c & a | d & ~a) + k[8] + 1163531501 | 0; b = (b << 20 | b >>> 12) + c | 0; a += (b & d | c & ~d) + k[13] - 1444681467 | 0; a = (a << 5 | a >>> 27) + b | 0; d += (a & c | b & ~c) + k[2] - 51403784 | 0; d = (d << 9 | d >>> 23) + a | 0; c += (d & b | a & ~b) + k[7] + 1735328473 | 0; c = (c << 14 | c >>> 18) + d | 0; b += (c & a | d & ~a) + k[12] - 1926607734 | 0; b = (b << 20 | b >>> 12) + c | 0; a += (b ^ c ^ d) + k[5] - 378558 | 0; a = (a << 4 | a >>> 28) + b | 0; d += (a ^ b ^ c) + k[8] - 2022574463 | 0; d = (d << 11 | d >>> 21) + a | 0; c += (d ^ a ^ b) + k[11] + 1839030562 | 0; c = (c << 16 | c >>> 16) + d | 0; b += (c ^ d ^ a) + k[14] - 35309556 | 0; b = (b << 23 | b >>> 9) + c | 0; a += (b ^ c ^ d) + k[1] - 1530992060 | 0; a = (a << 4 | a >>> 28) + b | 0; d += (a ^ b ^ c) + k[4] + 1272893353 | 0; d = (d << 11 | d >>> 21) + a | 0; c += (d ^ a ^ b) + k[7] - 155497632 | 0; c = (c << 16 | c >>> 16) + d | 0; b += (c ^ d ^ a) + k[10] - 1094730640 | 0; b = (b << 23 | b >>> 9) + c | 0; a += (b ^ c ^ d) + k[13] + 681279174 | 0; a = (a << 4 | a >>> 28) + b | 0; d += (a ^ b ^ c) + k[0] - 358537222 | 0; d = (d << 11 | d >>> 21) + a | 0; c += (d ^ a ^ b) + k[3] - 722521979 | 0; c = (c << 16 | c >>> 16) + d | 0; b += (c ^ d ^ a) + k[6] + 76029189 | 0; b = (b << 23 | b >>> 9) + c | 0; a += (b ^ c ^ d) + k[9] - 640364487 | 0; a = (a << 4 | a >>> 28) + b | 0; d += (a ^ b ^ c) + k[12] - 421815835 | 0; d = (d << 11 | d >>> 21) + a | 0; c += (d ^ a ^ b) + k[15] + 530742520 | 0; c = (c << 16 | c >>> 16) + d | 0; b += (c ^ d ^ a) + k[2] - 995338651 | 0; b = (b << 23 | b >>> 9) + c | 0; a += (c ^ (b | ~d)) + k[0] - 198630844 | 0; a = (a << 6 | a >>> 26) + b | 0; d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0; d = (d << 10 | d >>> 22) + a | 0; c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0; c = (c << 15 | c >>> 17) + d | 0; b += (d ^ (c | ~a)) + k[5] - 57434055 | 0; b = (b << 21 | b >>> 11) + c | 0; a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0; a = (a << 6 | a >>> 26) + b | 0; d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0; d = (d << 10 | d >>> 22) + a | 0; c += (a ^ (d | ~b)) + k[10] - 1051523 | 0; c = (c << 15 | c >>> 17) + d | 0; b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0; b = (b << 21 | b >>> 11) + c | 0; a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0; a = (a << 6 | a >>> 26) + b | 0; d += (b ^ (a | ~c)) + k[15] - 30611744 | 0; d = (d << 10 | d >>> 22) + a | 0; c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0; c = (c << 15 | c >>> 17) + d | 0; b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0; b = (b << 21 | b >>> 11) + c | 0; a += (c ^ (b | ~d)) + k[4] - 145523070 | 0; a = (a << 6 | a >>> 26) + b | 0; d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0; d = (d << 10 | d >>> 22) + a | 0; c += (a ^ (d | ~b)) + k[2] + 718787259 | 0; c = (c << 15 | c >>> 17) + d | 0; b += (d ^ (c | ~a)) + k[9] - 343485551 | 0; b = (b << 21 | b >>> 11) + c | 0; x[0] = a + x[0] | 0; x[1] = b + x[1] | 0; x[2] = c + x[2] | 0; x[3] = d + x[3] | 0; } function md5blk(s) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); } return md5blks; } function md5blk_array(a) { var md5blks = [], i; for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24); } return md5blks; } function md51(s) { var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi; for (i = 64; i <= n; i += 64) { md5cycle(state, md5blk(s.substring(i - 64, i))); } s = s.substring(i - 64); length = s.length; tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; for (i = 0; i < length; i += 1) { tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3); } tail[i >> 2] |= 128 << (i % 4 << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i += 1) { tail[i] = 0; } } tmp = n * 8; tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); lo = parseInt(tmp[2], 16); hi = parseInt(tmp[1], 16) || 0; tail[14] = lo; tail[15] = hi; md5cycle(state, tail); return state; } function md51_array(a) { var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi; for (i = 64; i <= n; i += 64) { md5cycle(state, md5blk_array(a.subarray(i - 64, i))); } a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0); length = a.length; tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; for (i = 0; i < length; i += 1) { tail[i >> 2] |= a[i] << (i % 4 << 3); } tail[i >> 2] |= 128 << (i % 4 << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i += 1) { tail[i] = 0; } } tmp = n * 8; tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); lo = parseInt(tmp[2], 16); hi = parseInt(tmp[1], 16) || 0; tail[14] = lo; tail[15] = hi; md5cycle(state, tail); return state; } function rhex(n) { var s = "", j; for (j = 0; j < 4; j += 1) { s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15]; } return s; } function hex(x) { var i; for (i = 0; i < x.length; i += 1) { x[i] = rhex(x[i]); } return x.join(""); } if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ; if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) { (function() { function clamp(val, length) { val = val | 0 || 0; if (val < 0) { return Math.max(val + length, 0); } return Math.min(val, length); } ArrayBuffer.prototype.slice = function(from, to) { var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray; if (to !== undefined$1) { end = clamp(to, length); } if (begin > end) { return new ArrayBuffer(0); } num = end - begin; target = new ArrayBuffer(num); targetArray = new Uint8Array(target); sourceArray = new Uint8Array(this, begin, num); targetArray.set(sourceArray); return target; }; })(); } function toUtf8(str) { if (/[\u0080-\uFFFF]/.test(str)) { str = unescape(encodeURIComponent(str)); } return str; } function utf8Str2ArrayBuffer(str, returnUInt8Array) { var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i; for (i = 0; i < length; i += 1) { arr[i] = str.charCodeAt(i); } return returnUInt8Array ? arr : buff; } function arrayBuffer2Utf8Str(buff) { return String.fromCharCode.apply(null, new Uint8Array(buff)); } function concatenateArrayBuffers(first, second, returnUInt8Array) { var result = new Uint8Array(first.byteLength + second.byteLength); result.set(new Uint8Array(first)); result.set(new Uint8Array(second), first.byteLength); return returnUInt8Array ? result : result.buffer; } function hexToBinaryString(hex) { var bytes = [], length = hex.length, x; for (x = 0; x < length - 1; x += 2) { bytes.push(parseInt(hex.substr(x, 2), 16)); } return String.fromCharCode.apply(String, bytes); } function SparkMD5() { this.reset(); } SparkMD5.prototype.append = function(str) { this.appendBinary(toUtf8(str)); return this; }; SparkMD5.prototype.appendBinary = function(contents) { this._buff += contents; this._length += contents.length; var length = this._buff.length, i; for (i = 64; i <= length; i += 64) { md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i))); } this._buff = this._buff.substring(i - 64); return this; }; SparkMD5.prototype.end = function(raw) { var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret; for (i = 0; i < length; i += 1) { tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3); } this._finish(tail, length); ret = hex(this._hash); if (raw) { ret = hexToBinaryString(ret); } this.reset(); return ret; }; SparkMD5.prototype.reset = function() { this._buff = ""; this._length = 0; this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ]; return this; }; SparkMD5.prototype.getState = function() { return { buff: this._buff, length: this._length, hash: this._hash.slice() }; }; SparkMD5.prototype.setState = function(state) { this._buff = state.buff; this._length = state.length; this._hash = state.hash; return this; }; SparkMD5.prototype.destroy = function() { delete this._hash; delete this._buff; delete this._length; }; SparkMD5.prototype._finish = function(tail, length) { var i = length, tmp, lo, hi; tail[i >> 2] |= 128 << (i % 4 << 3); if (i > 55) { md5cycle(this._hash, tail); for (i = 0; i < 16; i += 1) { tail[i] = 0; } } tmp = this._length * 8; tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); lo = parseInt(tmp[2], 16); hi = parseInt(tmp[1], 16) || 0; tail[14] = lo; tail[15] = hi; md5cycle(this._hash, tail); }; SparkMD5.hash = function(str, raw) { return SparkMD5.hashBinary(toUtf8(str), raw); }; SparkMD5.hashBinary = function(content, raw) { var hash = md51(content), ret = hex(hash); return raw ? hexToBinaryString(ret) : ret; }; SparkMD5.ArrayBuffer = function() { this.reset(); }; SparkMD5.ArrayBuffer.prototype.append = function(arr) { var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i; this._length += arr.byteLength; for (i = 64; i <= length; i += 64) { md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i))); } this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0); return this; }; SparkMD5.ArrayBuffer.prototype.end = function(raw) { var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret; for (i = 0; i < length; i += 1) { tail[i >> 2] |= buff[i] << (i % 4 << 3); } this._finish(tail, length); ret = hex(this._hash); if (raw) { ret = hexToBinaryString(ret); } this.reset(); return ret; }; SparkMD5.ArrayBuffer.prototype.reset = function() { this._buff = new Uint8Array(0); this._length = 0; this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ]; return this; }; SparkMD5.ArrayBuffer.prototype.getState = function() { var state = SparkMD5.prototype.getState.call(this); state.buff = arrayBuffer2Utf8Str(state.buff); return state; }; SparkMD5.ArrayBuffer.prototype.setState = function(state) { state.buff = utf8Str2ArrayBuffer(state.buff, true); return SparkMD5.prototype.setState.call(this, state); }; SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy; SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish; SparkMD5.ArrayBuffer.hash = function(arr, raw) { var hash = md51_array(new Uint8Array(arr)), ret = hex(hash); return raw ? hexToBinaryString(ret) : ret; }; return SparkMD5; })); })(sparkMd5); var SparkMD5 = sparkMd5.exports; const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; class FileChecksum { static create(file, callback) { const instance = new FileChecksum(file); instance.create(callback); } constructor(file) { this.file = file; this.chunkSize = 2097152; this.chunkCount = Math.ceil(this.file.size / this.chunkSize); this.chunkIndex = 0; } create(callback) { this.callback = callback; this.md5Buffer = new SparkMD5.ArrayBuffer; this.fileReader = new FileReader; this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event))); this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event))); this.readNextChunk(); } fileReaderDidLoad(event) { this.md5Buffer.append(event.target.result); if (!this.readNextChunk()) { const binaryDigest = this.md5Buffer.end(true); const base64digest = btoa(binaryDigest); this.callback(null, base64digest); } } fileReaderDidError(event) { this.callback(`Error reading ${this.file.name}`); } readNextChunk() { if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) { const start = this.chunkIndex * this.chunkSize; const end = Math.min(start + this.chunkSize, this.file.size); const bytes = fileSlice.call(this.file, start, end); this.fileReader.readAsArrayBuffer(bytes); this.chunkIndex++; return true; } else { return false; } } } function getMetaValue(name) { const element = findElement(document.head, `meta[name="${name}"]`); if (element) { return element.getAttribute("content"); } } function findElements(root, selector) { if (typeof root == "string") { selector = root; root = document; } const elements = root.querySelectorAll(selector); return toArray(elements); } function findElement(root, selector) { if (typeof root == "string") { selector = root; root = document; } return root.querySelector(selector); } function dispatchEvent$1(element, type, eventInit = {}) { const {disabled: disabled} = element; const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit; const event = document.createEvent("Event"); event.initEvent(type, bubbles || true, cancelable || true); event.detail = detail || {}; try { element.disabled = false; element.dispatchEvent(event); } finally { element.disabled = disabled; } return event; } function toArray(value) { if (Array.isArray(value)) { return value; } else if (Array.from) { return Array.from(value); } else { return [].slice.call(value); } } class BlobRecord { constructor(file, checksum, url, customHeaders = {}) { this.file = file; this.attributes = { filename: file.name, content_type: file.type || "application/octet-stream", byte_size: file.size, checksum: checksum }; this.xhr = new XMLHttpRequest; this.xhr.open("POST", url, true); this.xhr.responseType = "json"; this.xhr.setRequestHeader("Content-Type", "application/json"); this.xhr.setRequestHeader("Accept", "application/json"); this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); Object.keys(customHeaders).forEach((headerKey => { this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]); })); const csrfToken = getMetaValue("csrf-token"); if (csrfToken != undefined) { this.xhr.setRequestHeader("X-CSRF-Token", csrfToken); } this.xhr.addEventListener("load", (event => this.requestDidLoad(event))); this.xhr.addEventListener("error", (event => this.requestDidError(event))); } get status() { return this.xhr.status; } get response() { const {responseType: responseType, response: response} = this.xhr; if (responseType == "json") { return response; } else { return JSON.parse(response); } } create(callback) { this.callback = callback; this.xhr.send(JSON.stringify({ blob: this.attributes })); } requestDidLoad(event) { if (this.status >= 200 && this.status < 300) { const {response: response} = this; const {direct_upload: direct_upload} = response; delete response.direct_upload; this.attributes = response; this.directUploadData = direct_upload; this.callback(null, this.toJSON()); } else { this.requestDidError(event); } } requestDidError(event) { this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`); } toJSON() { const result = {}; for (const key in this.attributes) { result[key] = this.attributes[key]; } return result; } } class BlobUpload { constructor(blob) { this.blob = blob; this.file = blob.file; const {url: url, headers: headers} = blob.directUploadData; this.xhr = new XMLHttpRequest; this.xhr.open("PUT", url, true); this.xhr.responseType = "text"; for (const key in headers) { this.xhr.setRequestHeader(key, headers[key]); } this.xhr.addEventListener("load", (event => this.requestDidLoad(event))); this.xhr.addEventListener("error", (event => this.requestDidError(event))); } create(callback) { this.callback = callback; this.xhr.send(this.file.slice()); } requestDidLoad(event) { const {status: status, response: response} = this.xhr; if (status >= 200 && status < 300) { this.callback(null, response); } else { this.requestDidError(event); } } requestDidError(event) { this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`); } } let id = 0; class DirectUpload { constructor(file, url, delegate, customHeaders = {}) { this.id = ++id; this.file = file; this.url = url; this.delegate = delegate; this.customHeaders = customHeaders; } create(callback) { FileChecksum.create(this.file, ((error, checksum) => { if (error) { callback(error); return; } const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders); notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr); blob.create((error => { if (error) { callback(error); } else { const upload = new BlobUpload(blob); notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr); upload.create((error => { if (error) { callback(error); } else { callback(null, blob.toJSON()); } })); } })); })); } } function notify(object, methodName, ...messages) { if (object && typeof object[methodName] == "function") { return object[methodName](...messages); } } class DirectUploadController$1 { constructor(input, file) { this.input = input; this.file = file; this.directUpload = new DirectUpload(this.file, this.url, this); this.dispatch("initialize"); } start(callback) { const hiddenInput = document.createElement("input"); hiddenInput.type = "hidden"; hiddenInput.name = this.input.name; this.input.insertAdjacentElement("beforebegin", hiddenInput); this.dispatch("start"); this.directUpload.create(((error, attributes) => { if (error) { hiddenInput.parentNode.removeChild(hiddenInput); this.dispatchError(error); } else { hiddenInput.value = attributes.signed_id; } this.dispatch("end"); callback(error); })); } uploadRequestDidProgress(event) { const progress = event.loaded / event.total * 100; if (progress) { this.dispatch("progress", { progress: progress }); } } get url() { return this.input.getAttribute("data-direct-upload-url"); } dispatch(name, detail = {}) { detail.file = this.file; detail.id = this.directUpload.id; return dispatchEvent$1(this.input, `direct-upload:${name}`, { detail: detail }); } dispatchError(error) { const event = this.dispatch("error", { error: error }); if (!event.defaultPrevented) { alert(error); } } directUploadWillCreateBlobWithXHR(xhr) { this.dispatch("before-blob-request", { xhr: xhr }); } directUploadWillStoreFileWithXHR(xhr) { this.dispatch("before-storage-request", { xhr: xhr }); xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event))); } } const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])"; class DirectUploadsController { constructor(form) { this.form = form; this.inputs = findElements(form, inputSelector).filter((input => input.files.length)); } start(callback) { const controllers = this.createDirectUploadControllers(); const startNextController = () => { const controller = controllers.shift(); if (controller) { controller.start((error => { if (error) { callback(error); this.dispatch("end"); } else { startNextController(); } })); } else { callback(); this.dispatch("end"); } }; this.dispatch("start"); startNextController(); } createDirectUploadControllers() { const controllers = []; this.inputs.forEach((input => { toArray(input.files).forEach((file => { const controller = new DirectUploadController$1(input, file); controllers.push(controller); })); })); return controllers; } dispatch(name, detail = {}) { return dispatchEvent$1(this.form, `direct-uploads:${name}`, { detail: detail }); } } const processingAttribute = "data-direct-uploads-processing"; const submitButtonsByForm = new WeakMap; let started = false; function start() { if (!started) { started = true; document.addEventListener("click", didClick, true); document.addEventListener("submit", didSubmitForm, true); document.addEventListener("ajax:before", didSubmitRemoteElement); } } function didClick(event) { const {target: target} = event; if ((target.tagName == "INPUT" || target.tagName == "BUTTON") && target.type == "submit" && target.form) { submitButtonsByForm.set(target.form, target); } } function didSubmitForm(event) { handleFormSubmissionEvent(event); } function didSubmitRemoteElement(event) { if (event.target.tagName == "FORM") { handleFormSubmissionEvent(event); } } function handleFormSubmissionEvent(event) { const form = event.target; if (form.hasAttribute(processingAttribute)) { event.preventDefault(); return; } const controller = new DirectUploadsController(form); const {inputs: inputs} = controller; if (inputs.length) { event.preventDefault(); form.setAttribute(processingAttribute, ""); inputs.forEach(disable); controller.start((error => { form.removeAttribute(processingAttribute); if (error) { inputs.forEach(enable); } else { submitForm(form); } })); } } function submitForm(form) { let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]"); if (button) { const {disabled: disabled} = button; button.disabled = false; button.focus(); button.click(); button.disabled = disabled; } else { button = document.createElement("input"); button.type = "submit"; button.style.display = "none"; form.appendChild(button); button.click(); form.removeChild(button); } submitButtonsByForm.delete(form); } function disable(input) { input.disabled = true; } function enable(input) { input.disabled = false; } function autostart() { if (window.ActiveStorage) { start(); } } setTimeout(autostart, 1); class DirectUploadController { uploadedFile; file; directUpload; recordXHR; uploadXHR; callback = null; constructor(uploadedFile) { this.uploadedFile = uploadedFile; this.file = this.uploadedFile["file"]; this.directUpload = new DirectUpload(this.file, this.uploadedFile.url, this); } cancel() { this.directUpload.url = null; this.abortXHR(this.recordXHR); this.abortXHR(this.uploadXHR); } abortXHR(xhr) { if (!xhr) return; xhr.addEventListener("abort", () => { this.complete("aborted", {}); }); xhr.abort(); } start(callback) { this.callback = callback; this.dispatch("start"); this.directUpload.create((error, attributes) => { this.complete(error, attributes); }); } complete(error, _attributes) { if (error) { this.dispatchError(error); } this.dispatch("end"); this.callback(error); } uploadRequestDidProgress(event) { const progress = event.loaded / event.total * 100; if (progress) { this.dispatch("progress", { progress: progress }); } } dispatch(name, detail = {}) { return dispatchEvent(this.uploadedFile, `direct-upload:${name}`, { detail: { ...detail, file: this.file, id: this.directUpload.id, } }); } dispatchError(error) { this.dispatch("error", { error: error }); } directUploadWillCreateBlobWithXHR(xhr) { this.recordXHR = xhr; this.dispatch("before-blob-request", { xhr: xhr }); } directUploadWillStoreFileWithXHR(xhr) { this.uploadXHR = xhr; this.uploadedFile.value = this.recordXHR.response.signed_id; this.dispatch("before-storage-request", { xhr: xhr }); xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event))); } } function dispatchEvent(element, type, eventInit = {}) { const { disabled: disabled } = element; const { bubbles: bubbles, cancelable: cancelable, detail: detail } = eventInit; const event = document.createEvent("Event"); event.initEvent(type, bubbles || true, cancelable || true); event.detail = detail || {}; try { element.disabled = false; element.dispatchEvent(event); } finally { element.disabled = disabled; } return event; } class Max { uploadedFile; constructor(uploadedFile) { this.uploadedFile = uploadedFile; } get errors() { if (this.#errors) return this.#errors; this.#errors = []; if (!this.checkValidity()) { this.#errors.push(this.errorMessage); } return this.#errors; } #errors; checkValidity() { if (!this.uploadedFile.max) return true; return this.uploadedFile.size <= this.uploadedFile.max; } get errorMessage() { return [ `Must be smaller than ${this.formatBytes(this.uploadedFile.max)},`, `and "${this.uploadedFile.filename}" is ${this.formatBytes(this.uploadedFile.size)}.`, `Please attach a smaller file.`, ].join(" "); } formatBytes(bytes, decimals = 2) { if (bytes === 0) return '0 Bytes'; const k = 1024; const dm = decimals < 0 ? 0 : decimals; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + sizes[i]; } } class Accepts { uploadedFile; constructor(uploadedFile) { this.uploadedFile = uploadedFile; } get errors() { if (this.#errors) return this.#errors; this.#errors = []; const accepts = this.uploadedFile.accepts ? this.uploadedFile.accepts.split(/,\s*/) : []; if (accepts.length > 0 && !accepts.includes(this.uploadedFile.filetype)) { this.#errors.push(`Must be a ${this.joinWords(accepts)}.`); } return this.#errors; } #errors; joinWords(words) { if (words.length >= 3) { return (words.slice(0, -1) + [`or ${words.at(-1)}`]).join(", "); } else { return words.join(" or "); } } } const Extensions = { image: ["ase", "art", "bmp", "blp", "cd5", "cit", "cpt", "cr2", "cut", "dds", "dib", "djvu", "egt", "exif", "gif", "gpl", "grf", "icns", "ico", "iff", "jng", "jpeg", "jpg", "jfif", "jp2", "jps", "lbm", "max", "miff", "mng", "msp", "nef", "nitf", "ota", "pbm", "pc1", "pc2", "pc3", "pcf", "pcx", "pdn", "pgm", "PI1", "PI2", "PI3", "pict", "pct", "pnm", "pns", "ppm", "psb", "psd", "pdd", "psp", "px", "pxm", "pxr", "qfx", "raw", "rle", "sct", "sgi", "rgb", "int", "bw", "tga", "tiff", "tif", "vtf", "xbm", "xcf", "xpm", "3dv", "amf", "ai", "awg", "cgm", "cdr", "cmx", "dxf", "e2d", "egt", "eps", "fs", "gbr", "odg", "svg", "stl", "vrml", "x3d", "sxd", "v2d", "vnd", "wmf", "emf", "art", "xar", "png", "webp", "jxr", "hdp", "wdp", "cur", "ecw", "iff", "lbm", "liff", "nrrd", "pam", "pcx", "pgf", "sgi", "rgb", "rgba", "bw", "int", "inta", "sid", "ras", "sun", "tga", "heic", "heif"], video: ["3g2", "3gp", "3gpp", "aaf", "asf", "avchd", "avi", "drc", "flv", "m2v", "m3u8", "m4p", "m4v", "mkv", "mng", "mov", "mp2", "mp4", "mpe", "mpeg", "mpg", "mpv", "mxf", "nsv", "ogg", "ogv", "qt", "rm", "rmvb", "roq", "svi", "vob", "webm", "wmv", "yuv"], pdf: ["pdf"], getFileType: function (filename) { const normalized = filename.toString().split(".").at(-1).toLowerCase().trim(); if (this.video.includes(normalized)) return "video"; if (this.image.includes(normalized)) return "image"; if (this.pdf.includes(normalized)) return "pdf"; return "unknown"; } }; class FetchResponse { constructor (response) { this.response = response; } get statusCode () { return this.response.status } get redirected () { return this.response.redirected } get ok () { return this.response.ok } get unauthenticated () { return this.statusCode === 401 } get unprocessableEntity () { return this.statusCode === 422 } get authenticationURL () { return this.response.headers.get('WWW-Authenticate') } get contentType () { const contentType = this.response.headers.get('Content-Type') || ''; return contentType.replace(/;.*$/, '') } get headers () { return this.response.headers } get html () { if (this.contentType.match(/^(application|text)\/(html|xhtml\+xml)$/)) { return this.text } return Promise.reject(new Error(`Expected an HTML response but got "${this.contentType}" instead`)) } get json () { if (this.contentType.match(/^application\/.*json$/)) { return this.responseJson || (this.responseJson = this.response.json()) } return Promise.reject(new Error(`Expected a JSON response but got "${this.contentType}" instead`)) } get text () { return this.responseText || (this.responseText = this.response.text()) } get isTurboStream () { return this.contentType.match(/^text\/vnd\.turbo-stream\.html/) } async renderTurboStream () { if (this.isTurboStream) { if (window.Turbo) { await window.Turbo.renderStreamMessage(await this.text); } else { console.warn('You must set `window.Turbo = Turbo` to automatically process Turbo Stream events with request.js'); } } else { return Promise.reject(new Error(`Expected a Turbo Stream response but got "${this.contentType}" instead`)) } } } class RequestInterceptor { static register (interceptor) { this.interceptor = interceptor; } static get () { return this.interceptor } static reset () { this.interceptor = undefined; } } function getCookie (name) { const cookies = document.cookie ? document.cookie.split('; ') : []; const prefix = `${encodeURIComponent(name)}=`; const cookie = cookies.find(cookie => cookie.startsWith(prefix)); if (cookie) { const value = cookie.split('=').slice(1).join('='); if (value) { return decodeURIComponent(value) } } } function compact (object) { const result = {}; for (const key in object) { const value = object[key]; if (value !== undefined) { result[key] = value; } } return result } function metaContent (name) { const element = document.head.querySelector(`meta[name="${name}"]`); return element && element.content } function stringEntriesFromFormData (formData) { return [...formData].reduce((entries, [name, value]) => { return entries.concat(typeof value === 'string' ? [[name, value]] : []) }, []) } function mergeEntries (searchParams, entries) { for (const [name, value] of entries) { if (value instanceof window.File) continue if (searchParams.has(name)) { searchParams.delete(name); searchParams.set(name, value); } else { searchParams.append(name, value); } } } class FetchRequest { constructor (method, url, options = {}) { this.method = method; this.options = options; this.originalUrl = url.toString(); } async perform () { try { const requestInterceptor = RequestInterceptor.get(); if (requestInterceptor) { await requestInterceptor(this); } } catch (error) { console.error(error); } const response = new FetchResponse(await window.fetch(this.url, this.fetchOptions)); if (response.unauthenticated && response.authenticationURL) { return Promise.reject(window.location.href = response.authenticationURL) } if (response.ok && response.isTurboStream) { await response.renderTurboStream(); } return response } addHeader (key, value) { const headers = this.additionalHeaders; headers[key] = value; this.options.headers = headers; } get fetchOptions () { return { method: this.method.toUpperCase(), headers: this.headers, body: this.formattedBody, signal: this.signal, credentials: 'same-origin', redirect: this.redirect } } get headers () { return compact( Object.assign({ 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-Token': this.csrfToken, 'Content-Type': this.contentType, Accept: this.accept }, this.additionalHeaders) ) } get csrfToken () { return getCookie(metaContent('csrf-param')) || metaContent('csrf-token') } get contentType () { if (this.options.contentType) { return this.options.contentType } else if (this.body == null || this.body instanceof window.FormData) { return undefined } else if (this.body instanceof window.File) { return this.body.type } return 'application/json' } get accept () { switch (this.responseKind) { case 'html': return 'text/html, application/xhtml+xml' case 'turbo-stream': return 'text/vnd.turbo-stream.html, text/html, application/xhtml+xml' case 'json': return 'application/json, application/vnd.api+json' default: return '*/*' } } get body () { return this.options.body } get query () { const originalQuery = (this.originalUrl.split('?')[1] || '').split('#')[0]; const params = new URLSearchParams(originalQuery); let requestQuery = this.options.query; if (requestQuery instanceof window.FormData) { requestQuery = stringEntriesFromFormData(requestQuery); } else if (requestQuery instanceof window.URLSearchParams) { requestQuery = requestQuery.entries(); } else { requestQuery = Object.entries(requestQuery || {}); } mergeEntries(params, requestQuery); const query = params.toString(); return (query.length > 0 ? `?${query}` : '') } get url () { return (this.originalUrl.split('?')[0]).split('#')[0] + this.query } get responseKind () { return this.options.responseKind || 'html' } get signal () { return this.options.signal } get redirect () { return this.options.redirect || 'follow' } get additionalHeaders () { return this.options.headers || {} } get formattedBody () { const bodyIsAString = Object.prototype.toString.call(this.body) === '[object String]'; const contentTypeIsJson = this.headers['Content-Type'] === 'application/json'; if (contentTypeIsJson && !bodyIsAString) { return JSON.stringify(this.body) } return this.body } } const request = (verb, url, payload) => { const req = new FetchRequest(verb, url, { headers: { Accept: "application/json" }, body: payload, }); return req.perform().then(response => { if(response.response.ok) { return response.json } else { return response } }) }; const get = (url, payload) => request('get', url, payload); var DOCUMENT_FRAGMENT_NODE = 11; function morphAttrs(fromNode, toNode) { var toNodeAttrs = toNode.attributes; var attr; var attrName; var attrNamespaceURI; var attrValue; var fromValue; // document-fragments dont have attributes so lets not do anything if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE || fromNode.nodeType === DOCUMENT_FRAGMENT_NODE) { return; } // update attributes on original DOM element for (var i = toNodeAttrs.length - 1; i >= 0; i--) { attr = toNodeAttrs[i]; attrName = attr.name; attrNamespaceURI = attr.namespaceURI; attrValue = attr.value; if (attrNamespaceURI) { attrName = attr.localName || attrName; fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName); if (fromValue !== attrValue) { if (attr.prefix === 'xmlns'){ attrName = attr.name; // It's not allowed to set an attribute with the XMLNS namespace without specifying the `xmlns` prefix } fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue); } } else { fromValue = fromNode.getAttribute(attrName); if (fromValue !== attrValue) { fromNode.setAttribute(attrName, attrValue); } } } // Remove any extra attributes found on the original DOM element that // weren't found on the target element. var fromNodeAttrs = fromNode.attributes; for (var d = fromNodeAttrs.length - 1; d >= 0; d--) { attr = fromNodeAttrs[d]; attrName = attr.name; attrNamespaceURI = attr.namespaceURI; if (attrNamespaceURI) { attrName = attr.localName || attrName; if (!toNode.hasAttributeNS(attrNamespaceURI, attrName)) { fromNode.removeAttributeNS(attrNamespaceURI, attrName); } } else { if (!toNode.hasAttribute(attrName)) { fromNode.removeAttribute(attrName); } } } } var range; // Create a range object for efficently rendering strings to elements. var NS_XHTML = 'http://www.w3.org/1999/xhtml'; var doc = typeof document === 'undefined' ? undefined : document; var HAS_TEMPLATE_SUPPORT = !!doc && 'content' in doc.createElement('template'); var HAS_RANGE_SUPPORT = !!doc && doc.createRange && 'createContextualFragment' in doc.createRange(); function createFragmentFromTemplate(str) { var template = doc.createElement('template'); template.innerHTML = str; return template.content.childNodes[0]; } function createFragmentFromRange(str) { if (!range) { range = doc.createRange(); range.selectNode(doc.body); } var fragment = range.createContextualFragment(str); return fragment.childNodes[0]; } function createFragmentFromWrap(str) { var fragment = doc.createElement('body'); fragment.innerHTML = str; return fragment.childNodes[0]; } /** * This is about the same * var html = new DOMParser().parseFromString(str, 'text/html'); * return html.body.firstChild; * * @method toElement * @param {String} str */ function toElement(str) { str = str.trim(); if (HAS_TEMPLATE_SUPPORT) { // avoid restrictions on content for things like `Hi` which // createContextualFragment doesn't support //