code:
/**
* @vue/server-renderer v3.4.31
* (c) 2018-present Yuxi (Evan) You and Vue contributors
* @license MIT
**/
import { createVNode, ssrContextKey, ssrUtils, warn as warn$2, Fragment, Static, Comment, Text, mergeProps, createApp, initDirectivesForSSR } from 'vue';
import { isOn, isRenderableAttrValue, isSVGTag, propsToAttrMap, isBooleanAttr, includeBooleanAttr, isSSRSafeAttrName, escapeHtml, normalizeClass, isString, normalizeStyle, stringifyStyle, makeMap, isArray, toDisplayString, extend, isFunction, getGlobalThis, NOOP, isObject, looseEqual, looseIndexOf, isPromise, escapeHtmlComment, isVoidTag } from '@vue/shared';
export { includeBooleanAttr as ssrIncludeBooleanAttr } from '@vue/shared';

const shouldIgnoreProp = /* @__PURE__ */ makeMap(
  `,key,ref,innerHTML,textContent,ref_key,ref_for`
);
function ssrRenderAttrs(props, tag) {
  let ret = "";
  for (const key in props) {
    if (shouldIgnoreProp(key) || isOn(key) || tag === "textarea" && key === "value") {
      continue;
    }
    const value = props[key];
    if (key === "class") {
      ret += ` class="${ssrRenderClass(value)}"`;
    } else if (key === "style") {
      ret += ` style="${ssrRenderStyle(value)}"`;
    } else {
      ret += ssrRenderDynamicAttr(key, value, tag);
    }
  }
  return ret;
}
function ssrRenderDynamicAttr(key, value, tag) {
  if (!isRenderableAttrValue(value)) {
    return ``;
  }
  const attrKey = tag && (tag.indexOf("-") > 0 || isSVGTag(tag)) ? key : propsToAttrMap[key] || key.toLowerCase();
  if (isBooleanAttr(attrKey)) {
    return includeBooleanAttr(value) ? ` ${attrKey}` : ``;
  } else if (isSSRSafeAttrName(attrKey)) {
    return value === "" ? ` ${attrKey}` : ` ${attrKey}="${escapeHtml(value)}"`;
  } else {
    console.warn(
      `[@vue/server-renderer] Skipped rendering unsafe attribute name: ${attrKey}`
    );
    return ``;
  }
}
function ssrRenderAttr(key, value) {
  if (!isRenderableAttrValue(value)) {
    return ``;
  }
  return ` ${key}="${escapeHtml(value)}"`;
}
function ssrRenderClass(raw) {
  return escapeHtml(normalizeClass(raw));
}
function ssrRenderStyle(raw) {
  if (!raw) {
    return "";
  }
  if (isString(raw)) {
    return escapeHtml(raw);
  }
  const styles = normalizeStyle(raw);
  return escapeHtml(stringifyStyle(styles));
}

function ssrRenderComponent(comp, props = null, children = null, parentComponent = null, slotScopeId) {
  return renderComponentVNode(
    createVNode(comp, props, children),
    parentComponent,
    slotScopeId
  );
}

function ssrRenderSlot(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId) {
  push(`<!--[-->`);
  ssrRenderSlotInner(
    slots,
    slotName,
    slotProps,
    fallbackRenderFn,
    push,
    parentComponent,
    slotScopeId
  );
  push(`<!--]-->`);
}
function ssrRenderSlotInner(slots, slotName, slotProps, fallbackRenderFn, push, parentComponent, slotScopeId, transition) {
  const slotFn = slots[slotName];
  if (slotFn) {
    const slotBuffer = [];
    const bufferedPush = (item) => {
      slotBuffer.push(item);
    };
    const ret = slotFn(
      slotProps,
      bufferedPush,
      parentComponent,
      slotScopeId ? " " + slotScopeId : ""
    );
    if (isArray(ret)) {
      renderVNodeChildren(push, ret, parentComponent, slotScopeId);
    } else {
      let isEmptySlot = true;
      if (transition) {
        isEmptySlot = false;
      } else {
        for (let i = 0; i < slotBuffer.length; i++) {
          if (!isComment(slotBuffer[i])) {
            isEmptySlot = false;
            break;
          }
        }
      }
      if (isEmptySlot) {
        if (fallbackRenderFn) {
          fallbackRenderFn();
        }
      } else {
        let start = 0;
        let end = slotBuffer.length;
        if (transition && slotBuffer[0] === "<!--[-->" && slotBuffer[end - 1] === "<!--]-->") {
          start++;
          end--;
        }
        for (let i = start; i < end; i++) {
          push(slotBuffer[i]);
        }
      }
    }
  } else if (fallbackRenderFn) {
    fallbackRenderFn();
  }
}
const commentTestRE = /^<!--[\s\S]*-->$/;
const commentRE = /<!--[^]*?-->/gm;
function isComment(item) {
  if (typeof item !== "string" || !commentTestRE.test(item)) return false;
  if (item.length <= 8) return true;
  return !item.replace(commentRE, "").trim();
}

function ssrRenderTeleport(parentPush, contentRenderFn, target, disabled, parentComponent) {
  parentPush("<!--teleport start-->");
  const context = parentComponent.appContext.provides[ssrContextKey];
  const teleportBuffers = context.__teleportBuffers || (context.__teleportBuffers = {});
  const targetBuffer = teleportBuffers[target] || (teleportBuffers[target] = []);
  const bufferIndex = targetBuffer.length;
  let teleportContent;
  if (disabled) {
    contentRenderFn(parentPush);
    teleportContent = `<!--teleport anchor-->`;
  } else {
    const { getBuffer, push } = createBuffer();
    contentRenderFn(push);
    push(`<!--teleport anchor-->`);
    teleportContent = getBuffer();
  }
  targetBuffer.splice(bufferIndex, 0, teleportContent);
  parentPush("<!--teleport end-->");
}

function ssrInterpolate(value) {
  return escapeHtml(toDisplayString(value));
}

let activeEffect;
let shouldTrack = true;
const trackStack = [];
function pauseTracking() {
  trackStack.push(shouldTrack);
  shouldTrack = false;
}
function resetTracking() {
  const last = trackStack.pop();
  shouldTrack = last === void 0 ? true : last;
}
function trackEffect(effect2, dep, debuggerEventExtraInfo) {
  var _a;
  if (dep.get(effect2) !== effect2._trackId) {
    dep.set(effect2, effect2._trackId);
    const oldDep = effect2.deps[effect2._depsLength];
    if (oldDep !== dep) {
      effect2.deps[effect2._depsLength++] = dep;
    } else {
      effect2._depsLength++;
    }
    if (!!(process.env.NODE_ENV !== "production")) {
      (_a = effect2.onTrack) == null ? void 0 : _a.call(effect2, extend({ effect: effect2 }, debuggerEventExtraInfo));
    }
  }
}

const createDep = (cleanup, computed) => {
  const dep = /* @__PURE__ */ new Map();
  dep.cleanup = cleanup;
  dep.computed = computed;
  return dep;
};

const targetMap = /* @__PURE__ */ new WeakMap();
Symbol(!!(process.env.NODE_ENV !== "production") ? "iterate" : "");
Symbol(!!(process.env.NODE_ENV !== "production") ? "Map key iterate" : "");
function track(target, type, key) {
  if (shouldTrack && activeEffect) {
    let depsMap = targetMap.get(target);
    if (!depsMap) {
      targetMap.set(target, depsMap = /* @__PURE__ */ new Map());
    }
    let dep = depsMap.get(key);
    if (!dep) {
      depsMap.set(key, dep = createDep(() => depsMap.delete(key)));
    }
    trackEffect(
      activeEffect,
      dep,
      !!(process.env.NODE_ENV !== "production") ? {
        target,
        type,
        key
      } : void 0
    );
  }
}

function toRaw(observed) {
  const raw = observed && observed["__v_raw"];
  return raw ? toRaw(raw) : observed;
}

function isRef(r) {
  return !!(r && r.__v_isRef === true);
}

const stack = [];
function pushWarningContext(vnode) {
  stack.push(vnode);
}
function popWarningContext() {
  stack.pop();
}
function warn$1(msg, ...args) {
  pauseTracking();
  const instance = stack.length ? stack[stack.length - 1].component : null;
  const appWarnHandler = instance && instance.appContext.config.warnHandler;
  const trace = getComponentTrace();
  if (appWarnHandler) {
    callWithErrorHandling(
      appWarnHandler,
      instance,
      11,
      [
        // eslint-disable-next-line no-restricted-syntax
        msg + args.map((a) => {
          var _a, _b;
          return (_b = (_a = a.toString) == null ? void 0 : _a.call(a)) != null ? _b : JSON.stringify(a);
        }).join(""),
        instance && instance.proxy,
        trace.map(
          ({ vnode }) => `at <${formatComponentName(instance, vnode.type)}>`
        ).join("\n"),
        trace
      ]
    );
  } else {
    const warnArgs = [`[Vue warn]: ${msg}`, ...args];
    if (trace.length && // avoid spamming console during tests
    true) {
      warnArgs.push(`
`, ...formatTrace(trace));
    }
    console.warn(...warnArgs);
  }
  resetTracking();
}
function getComponentTrace() {
  let currentVNode = stack[stack.length - 1];
  if (!currentVNode) {
    return [];
  }
  const normalizedStack = [];
  while (currentVNode) {
    const last = normalizedStack[0];
    if (last && last.vnode === currentVNode) {
      last.recurseCount++;
    } else {
      normalizedStack.push({
        vnode: currentVNode,
        recurseCount: 0
      });
    }
    const parentInstance = currentVNode.component && currentVNode.component.parent;
    currentVNode = parentInstance && parentInstance.vnode;
  }
  return normalizedStack;
}
function formatTrace(trace) {
  const logs = [];
  trace.forEach((entry, i) => {
    logs.push(...i === 0 ? [] : [`
`], ...formatTraceEntry(entry));
  });
  return logs;
}
function formatTraceEntry({ vnode, recurseCount }) {
  const postfix = recurseCount > 0 ? `... (${recurseCount} recursive calls)` : ``;
  const isRoot = vnode.component ? vnode.component.parent == null : false;
  const open = ` at <${formatComponentName(
    vnode.component,
    vnode.type,
    isRoot
  )}`;
  const close = `>` + postfix;
  return vnode.props ? [open, ...formatProps(vnode.props), close] : [open + close];
}
function formatProps(props) {
  const res = [];
  const keys = Object.keys(props);
  keys.slice(0, 3).forEach((key) => {
    res.push(...formatProp(key, props[key]));
  });
  if (keys.length > 3) {
    res.push(` ...`);
  }
  return res;
}
function formatProp(key, value, raw) {
  if (isString(value)) {
    value = JSON.stringify(value);
    return raw ? value : [`${key}=${value}`];
  } else if (typeof value === "number" || typeof value === "boolean" || value == null) {
    return raw ? value : [`${key}=${value}`];
  } else if (isRef(value)) {
    value = formatProp(key, toRaw(value.value), true);
    return raw ? value : [`${key}=Ref<`, value, `>`];
  } else if (isFunction(value)) {
    return [`${key}=fn${value.name ? `<${value.name}>` : ``}`];
  } else {
    value = toRaw(value);
    return raw ? value : [`${key}=`, value];
  }
}

const ErrorTypeStrings = {
  ["sp"]: "serverPrefetch hook",
  ["bc"]: "beforeCreate hook",
  ["c"]: "created hook",
  ["bm"]: "beforeMount hook",
  ["m"]: "mounted hook",
  ["bu"]: "beforeUpdate hook",
  ["u"]: "updated",
  ["bum"]: "beforeUnmount hook",
  ["um"]: "unmounted hook",
  ["a"]: "activated hook",
  ["da"]: "deactivated hook",
  ["ec"]: "errorCaptured hook",
  ["rtc"]: "renderTracked hook",
  ["rtg"]: "renderTriggered hook",
  [0]: "setup function",
  [1]: "render function",
  [2]: "watcher getter",
  [3]: "watcher callback",
  [4]: "watcher cleanup function",
  [5]: "native event handler",
  [6]: "component event handler",
  [7]: "vnode hook",
  [8]: "directive hook",
  [9]: "transition hook",
  [10]: "app errorHandler",
  [11]: "app warnHandler",
  [12]: "ref function",
  [13]: "async component loader",
  [14]: "scheduler flush. This is likely a Vue internals bug. Please open an issue at https://github.com/vuejs/core ."
};
function callWithErrorHandling(fn, instance, type, args) {
  try {
    return args ? fn(...args) : fn();
  } catch (err) {
    handleError(err, instance, type);
  }
}
function handleError(err, instance, type, throwInDev = true) {
  const contextVNode = instance ? instance.vnode : null;
  if (instance) {
    let cur = instance.parent;
    const exposedInstance = instance.proxy;
    const errorInfo = !!(process.env.NODE_ENV !== "production") ? ErrorTypeStrings[type] : `https://vuejs.org/error-reference/#runtime-${type}`;
    while (cur) {
      const errorCapturedHooks = cur.ec;
      if (errorCapturedHooks) {
        for (let i = 0; i < errorCapturedHooks.length; i++) {
          if (errorCapturedHooks[i](err, exposedInstance, errorInfo) === false) {
            return;
          }
        }
      }
      cur = cur.parent;
    }
    const appErrorHandler = instance.appContext.config.errorHandler;
    if (appErrorHandler) {
      pauseTracking();
      callWithErrorHandling(
        appErrorHandler,
        null,
        10,
        [err, exposedInstance, errorInfo]
      );
      resetTracking();
      return;
    }
  }
  logError(err, type, contextVNode, throwInDev);
}
function logError(err, type, contextVNode, throwInDev = true) {
  if (!!(process.env.NODE_ENV !== "production")) {
    const info = ErrorTypeStrings[type];
    if (contextVNode) {
      pushWarningContext(contextVNode);
    }
    warn$1(`Unhandled error${info ? ` during execution of ${info}` : ``}`);
    if (contextVNode) {
      popWarningContext();
    }
    if (throwInDev) {
      throw err;
    } else {
      console.error(err);
    }
  } else {
    console.error(err);
  }
}

let devtools;
let buffer = [];
function setDevtoolsHook(hook, target) {
  var _a, _b;
  devtools = hook;
  if (devtools) {
    devtools.enabled = true;
    buffer.forEach(({ event, args }) => devtools.emit(event, ...args));
    buffer = [];
  } else if (
    // handle late devtools injection - only do this if we are in an actual
    // browser environment to avoid the timer handle stalling test runner exit
    // (#4815)
    typeof window !== "undefined" && // some envs mock window but not fully
    window.HTMLElement && // also exclude jsdom
    // eslint-disable-next-line no-restricted-syntax
    !((_b = (_a = window.navigator) == null ? void 0 : _a.userAgent) == null ? void 0 : _b.includes("jsdom"))
  ) {
    const replay = target.__VUE_DEVTOOLS_HOOK_REPLAY__ = target.__VUE_DEVTOOLS_HOOK_REPLAY__ || [];
    replay.push((newHook) => {
      setDevtoolsHook(newHook, target);
    });
    setTimeout(() => {
      if (!devtools) {
        target.__VUE_DEVTOOLS_HOOK_REPLAY__ = null;
        buffer = [];
      }
    }, 3e3);
  } else {
    buffer = [];
  }
}

{
  const g = getGlobalThis();
  const registerGlobalSetter = (key, setter) => {
    let setters;
    if (!(setters = g[key])) setters = g[key] = [];
    setters.push(setter);
    return (v) => {
      if (setters.length > 1) setters.forEach((set) => set(v));
      else setters[0](v);
    };
  };
  registerGlobalSetter(
    `__VUE_INSTANCE_SETTERS__`,
    (v) => v
  );
  registerGlobalSetter(
    `__VUE_SSR_SETTERS__`,
    (v) => v
  );
}
!!(process.env.NODE_ENV !== "production") ? {
  get(target, key) {
    track(target, "get", "");
    return target[key];
  },
  set() {
    warn$1(`setupContext.attrs is readonly.`);
    return false;
  },
  deleteProperty() {
    warn$1(`setupContext.attrs is readonly.`);
    return false;
  }
} : {
  get(target, key) {
    track(target, "get", "");
    return target[key];
  }
};
const classifyRE = /(?:^|[-_])(\w)/g;
const classify = (str) => str.replace(classifyRE, (c) => c.toUpperCase()).replace(/[-_]/g, "");
function getComponentName(Component, includeInferred = true) {
  return isFunction(Component) ? Component.displayName || Component.name : Component.name || includeInferred && Component.__name;
}
function formatComponentName(instance, Component, isRoot = false) {
  let name = getComponentName(Component);
  if (!name && Component.__file) {
    const match = Component.__file.match(/([^/\\]+)\.\w+$/);
    if (match) {
      name = match[1];
    }
  }
  if (!name && instance && instance.parent) {
    const inferFromRegistry = (registry) => {
      for (const key in registry) {
        if (registry[key] === Component) {
          return key;
        }
      }
    };
    name = inferFromRegistry(
      instance.components || instance.parent.type.components
    ) || inferFromRegistry(instance.appContext.components);
  }
  return name ? classify(name) : isRoot ? `App` : `Anonymous`;
}

const warn = !!(process.env.NODE_ENV !== "production") ? warn$1 : NOOP;
!!(process.env.NODE_ENV !== "production") || true ? devtools : void 0;
!!(process.env.NODE_ENV !== "production") || true ? setDevtoolsHook : NOOP;

function ssrRenderList(source, renderItem) {
  if (isArray(source) || isString(source)) {
    for (let i = 0, l = source.length; i < l; i++) {
      renderItem(source[i], i);
    }
  } else if (typeof source === "number") {
    if (!!(process.env.NODE_ENV !== "production") && !Number.isInteger(source)) {
      warn(`The v-for range expect an integer value but got ${source}.`);
      return;
    }
    for (let i = 0; i < source; i++) {
      renderItem(i + 1, i);
    }
  } else if (isObject(source)) {
    if (source[Symbol.iterator]) {
      const arr = Array.from(source);
      for (let i = 0, l = arr.length; i < l; i++) {
        renderItem(arr[i], i);
      }
    } else {
      const keys = Object.keys(source);
      for (let i = 0, l = keys.length; i < l; i++) {
        const key = keys[i];
        renderItem(source[key], key, i);
      }
    }
  }
}

async function ssrRenderSuspense(push, { default: renderContent }) {
  if (renderContent) {
    renderContent();
  } else {
    push(`<!---->`);
  }
}

function ssrGetDirectiveProps(instance, dir, value, arg, modifiers = {}) {
  if (typeof dir !== "function" && dir.getSSRProps) {
    return dir.getSSRProps(
      {
        dir,
        instance: ssrUtils.getComponentPublicInstance(instance.$),
        value,
        oldValue: void 0,
        arg,
        modifiers
      },
      null
    ) || {};
  }
  return {};
}

const ssrLooseEqual = looseEqual;
function ssrLooseContain(arr, value) {
  return looseIndexOf(arr, value) > -1;
}
function ssrRenderDynamicModel(type, model, value) {
  switch (type) {
    case "radio":
      return looseEqual(model, value) ? " checked" : "";
    case "checkbox":
      return (isArray(model) ? ssrLooseContain(model, value) : model) ? " checked" : "";
    default:
      return ssrRenderAttr("value", model);
  }
}
function ssrGetDynamicModelProps(existingProps = {}, model) {
  const { type, value } = existingProps;
  switch (type) {
    case "radio":
      return looseEqual(model, value) ? { checked: true } : null;
    case "checkbox":
      return (isArray(model) ? ssrLooseContain(model, value) : model) ? { checked: true } : null;
    default:
      return { value: model };
  }
}

function ssrCompile(template, instance) {
  {
    throw new Error(
      `On-the-fly template compilation is not supported in the ESM build of @vue/server-renderer. All templates must be pre-compiled into render functions.`
    );
  }
}

const {
  createComponentInstance,
  setCurrentRenderingInstance,
  setupComponent,
  renderComponentRoot,
  normalizeVNode
} = ssrUtils;
function createBuffer() {
  let appendable = false;
  const buffer = [];
  return {
    getBuffer() {
      return buffer;
    },
    push(item) {
      const isStringItem = isString(item);
      if (appendable && isStringItem) {
        buffer[buffer.length - 1] += item;
      } else {
        buffer.push(item);
      }
      appendable = isStringItem;
      if (isPromise(item) || isArray(item) && item.hasAsync) {
        buffer.hasAsync = true;
      }
    }
  };
}
function renderComponentVNode(vnode, parentComponent = null, slotScopeId) {
  const instance = createComponentInstance(vnode, parentComponent, null);
  const res = setupComponent(
    instance,
    true
    /* isSSR */
  );
  const hasAsyncSetup = isPromise(res);
  const prefetches = instance.sp;
  if (hasAsyncSetup || prefetches) {
    let p = hasAsyncSetup ? res : Promise.resolve();
    if (prefetches) {
      p = p.then(
        () => Promise.all(
          prefetches.map((prefetch) => prefetch.call(instance.proxy))
        )
      ).catch(NOOP);
    }
    return p.then(() => renderComponentSubTree(instance, slotScopeId));
  } else {
    return renderComponentSubTree(instance, slotScopeId);
  }
}
function renderComponentSubTree(instance, slotScopeId) {
  const comp = instance.type;
  const { getBuffer, push } = createBuffer();
  if (isFunction(comp)) {
    let root = renderComponentRoot(instance);
    if (!comp.props) {
      for (const key in instance.attrs) {
        if (key.startsWith(`data-v-`)) {
          (root.props || (root.props = {}))[key] = ``;
        }
      }
    }
    renderVNode(push, instance.subTree = root, instance, slotScopeId);
  } else {
    if ((!instance.render || instance.render === NOOP) && !instance.ssrRender && !comp.ssrRender && isString(comp.template)) {
      comp.ssrRender = ssrCompile(comp.template);
    }
    for (const e of instance.scope.effects) {
      if (e.computed) {
        e.computed._dirty = true;
        e.computed._cacheable = true;
      }
    }
    const ssrRender = instance.ssrRender || comp.ssrRender;
    if (ssrRender) {
      let attrs = instance.inheritAttrs !== false ? instance.attrs : void 0;
      let hasCloned = false;
      let cur = instance;
      while (true) {
        const scopeId = cur.vnode.scopeId;
        if (scopeId) {
          if (!hasCloned) {
            attrs = { ...attrs };
            hasCloned = true;
          }
          attrs[scopeId] = "";
        }
        const parent = cur.parent;
        if (parent && parent.subTree && parent.subTree === cur.vnode) {
          cur = parent;
        } else {
          break;
        }
      }
      if (slotScopeId) {
        if (!hasCloned) attrs = { ...attrs };
        const slotScopeIdList = slotScopeId.trim().split(" ");
        for (let i = 0; i < slotScopeIdList.length; i++) {
          attrs[slotScopeIdList[i]] = "";
        }
      }
      const prev = setCurrentRenderingInstance(instance);
      try {
        ssrRender(
          instance.proxy,
          push,
          instance,
          attrs,
          // compiler-optimized bindings
          instance.props,
          instance.setupState,
          instance.data,
          instance.ctx
        );
      } finally {
        setCurrentRenderingInstance(prev);
      }
    } else if (instance.render && instance.render !== NOOP) {
      renderVNode(
        push,
        instance.subTree = renderComponentRoot(instance),
        instance,
        slotScopeId
      );
    } else {
      const componentName = comp.name || comp.__file || `<Anonymous>`;
      warn$2(`Component ${componentName} is missing template or render function.`);
      push(`<!---->`);
    }
  }
  return getBuffer();
}
function renderVNode(push, vnode, parentComponent, slotScopeId) {
  const { type, shapeFlag, children } = vnode;
  switch (type) {
    case Text:
      push(escapeHtml(children));
      break;
    case Comment:
      push(
        children ? `<!--${escapeHtmlComment(children)}-->` : `<!---->`
      );
      break;
    case Static:
      push(children);
      break;
    case Fragment:
      if (vnode.slotScopeIds) {
        slotScopeId = (slotScopeId ? slotScopeId + " " : "") + vnode.slotScopeIds.join(" ");
      }
      push(`<!--[-->`);
      renderVNodeChildren(
        push,
        children,
        parentComponent,
        slotScopeId
      );
      push(`<!--]-->`);
      break;
    default:
      if (shapeFlag & 1) {
        renderElementVNode(push, vnode, parentComponent, slotScopeId);
      } else if (shapeFlag & 6) {
        push(renderComponentVNode(vnode, parentComponent, slotScopeId));
      } else if (shapeFlag & 64) {
        renderTeleportVNode(push, vnode, parentComponent, slotScopeId);
      } else if (shapeFlag & 128) {
        renderVNode(push, vnode.ssContent, parentComponent, slotScopeId);
      } else {
        warn$2(
          "[@vue/server-renderer] Invalid VNode type:",
          type,
          `(${typeof type})`
        );
      }
  }
}
function renderVNodeChildren(push, children, parentComponent, slotScopeId) {
  for (let i = 0; i < children.length; i++) {
    renderVNode(push, normalizeVNode(children[i]), parentComponent, slotScopeId);
  }
}
function renderElementVNode(push, vnode, parentComponent, slotScopeId) {
  const tag = vnode.type;
  let { props, children, shapeFlag, scopeId, dirs } = vnode;
  let openTag = `<${tag}`;
  if (dirs) {
    props = applySSRDirectives(vnode, props, dirs);
  }
  if (props) {
    openTag += ssrRenderAttrs(props, tag);
  }
  if (scopeId) {
    openTag += ` ${scopeId}`;
  }
  let curParent = parentComponent;
  let curVnode = vnode;
  while (curParent && curVnode === curParent.subTree) {
    curVnode = curParent.vnode;
    if (curVnode.scopeId) {
      openTag += ` ${curVnode.scopeId}`;
    }
    curParent = curParent.parent;
  }
  if (slotScopeId) {
    openTag += ` ${slotScopeId}`;
  }
  push(openTag + `>`);
  if (!isVoidTag(tag)) {
    let hasChildrenOverride = false;
    if (props) {
      if (props.innerHTML) {
        hasChildrenOverride = true;
        push(props.innerHTML);
      } else if (props.textContent) {
        hasChildrenOverride = true;
        push(escapeHtml(props.textContent));
      } else if (tag === "textarea" && props.value) {
        hasChildrenOverride = true;
        push(escapeHtml(props.value));
      }
    }
    if (!hasChildrenOverride) {
      if (shapeFlag & 8) {
        push(escapeHtml(children));
      } else if (shapeFlag & 16) {
        renderVNodeChildren(
          push,
          children,
          parentComponent,
          slotScopeId
        );
      }
    }
    push(`</${tag}>`);
  }
}
function applySSRDirectives(vnode, rawProps, dirs) {
  const toMerge = [];
  for (let i = 0; i < dirs.length; i++) {
    const binding = dirs[i];
    const {
      dir: { getSSRProps }
    } = binding;
    if (getSSRProps) {
      const props = getSSRProps(binding, vnode);
      if (props) toMerge.push(props);
    }
  }
  return mergeProps(rawProps || {}, ...toMerge);
}
function renderTeleportVNode(push, vnode, parentComponent, slotScopeId) {
  const target = vnode.props && vnode.props.to;
  const disabled = vnode.props && vnode.props.disabled;
  if (!target) {
    if (!disabled) {
      warn$2(`[@vue/server-renderer] Teleport is missing target prop.`);
    }
    return [];
  }
  if (!isString(target)) {
    warn$2(
      `[@vue/server-renderer] Teleport target must be a query selector string.`
    );
    return [];
  }
  ssrRenderTeleport(
    push,
    (push2) => {
      renderVNodeChildren(
        push2,
        vnode.children,
        parentComponent,
        slotScopeId
      );
    },
    target,
    disabled || disabled === "",
    parentComponent
  );
}

const { isVNode: isVNode$1 } = ssrUtils;
async function unrollBuffer$1(buffer) {
  if (buffer.hasAsync) {
    let ret = "";
    for (let i = 0; i < buffer.length; i++) {
      let item = buffer[i];
      if (isPromise(item)) {
        item = await item;
      }
      if (isString(item)) {
        ret += item;
      } else {
        ret += await unrollBuffer$1(item);
      }
    }
    return ret;
  } else {
    return unrollBufferSync$1(buffer);
  }
}
function unrollBufferSync$1(buffer) {
  let ret = "";
  for (let i = 0; i < buffer.length; i++) {
    let item = buffer[i];
    if (isString(item)) {
      ret += item;
    } else {
      ret += unrollBufferSync$1(item);
    }
  }
  return ret;
}
async function renderToString(input, context = {}) {
  if (isVNode$1(input)) {
    return renderToString(createApp({ render: () => input }), context);
  }
  const vnode = createVNode(input._component, input._props);
  vnode.appContext = input._context;
  input.provide(ssrContextKey, context);
  const buffer = await renderComponentVNode(vnode);
  const result = await unrollBuffer$1(buffer);
  await resolveTeleports(context);
  if (context.__watcherHandles) {
    for (const unwatch of context.__watcherHandles) {
      unwatch();
    }
  }
  return result;
}
async function resolveTeleports(context) {
  if (context.__teleportBuffers) {
    context.teleports = context.teleports || {};
    for (const key in context.__teleportBuffers) {
      context.teleports[key] = await unrollBuffer$1(
        await Promise.all([context.__teleportBuffers[key]])
      );
    }
  }
}

const { isVNode } = ssrUtils;
async function unrollBuffer(buffer, stream) {
  if (buffer.hasAsync) {
    for (let i = 0; i < buffer.length; i++) {
      let item = buffer[i];
      if (isPromise(item)) {
        item = await item;
      }
      if (isString(item)) {
        stream.push(item);
      } else {
        await unrollBuffer(item, stream);
      }
    }
  } else {
    unrollBufferSync(buffer, stream);
  }
}
function unrollBufferSync(buffer, stream) {
  for (let i = 0; i < buffer.length; i++) {
    let item = buffer[i];
    if (isString(item)) {
      stream.push(item);
    } else {
      unrollBufferSync(item, stream);
    }
  }
}
function renderToSimpleStream(input, context, stream) {
  if (isVNode(input)) {
    return renderToSimpleStream(
      createApp({ render: () => input }),
      context,
      stream
    );
  }
  const vnode = createVNode(input._component, input._props);
  vnode.appContext = input._context;
  input.provide(ssrContextKey, context);
  Promise.resolve(renderComponentVNode(vnode)).then((buffer) => unrollBuffer(buffer, stream)).then(() => resolveTeleports(context)).then(() => {
    if (context.__watcherHandles) {
      for (const unwatch of context.__watcherHandles) {
        unwatch();
      }
    }
  }).then(() => stream.push(null)).catch((error) => {
    stream.destroy(error);
  });
  return stream;
}
function renderToStream(input, context = {}) {
  console.warn(
    `[@vue/server-renderer] renderToStream is deprecated - use renderToNodeStream instead.`
  );
  return renderToNodeStream(input, context);
}
function renderToNodeStream(input, context = {}) {
  {
    throw new Error(
      `ESM build of renderToStream() does not support renderToNodeStream(). Use pipeToNodeWritable() with an existing Node.js Writable stream instance instead.`
    );
  }
}
function pipeToNodeWritable(input, context = {}, writable) {
  renderToSimpleStream(input, context, {
    push(content) {
      if (content != null) {
        writable.write(content);
      } else {
        writable.end();
      }
    },
    destroy(err) {
      writable.destroy(err);
    }
  });
}
function renderToWebStream(input, context = {}) {
  if (typeof ReadableStream !== "function") {
    throw new Error(
      `ReadableStream constructor is not available in the global scope. If the target environment does support web streams, consider using pipeToWebWritable() with an existing WritableStream instance instead.`
    );
  }
  const encoder = new TextEncoder();
  let cancelled = false;
  return new ReadableStream({
    start(controller) {
      renderToSimpleStream(input, context, {
        push(content) {
          if (cancelled) return;
          if (content != null) {
            controller.enqueue(encoder.encode(content));
          } else {
            controller.close();
          }
        },
        destroy(err) {
          controller.error(err);
        }
      });
    },
    cancel() {
      cancelled = true;
    }
  });
}
function pipeToWebWritable(input, context = {}, writable) {
  const writer = writable.getWriter();
  const encoder = new TextEncoder();
  let hasReady = false;
  try {
    hasReady = isPromise(writer.ready);
  } catch (e) {
  }
  renderToSimpleStream(input, context, {
    async push(content) {
      if (hasReady) {
        await writer.ready;
      }
      if (content != null) {
        return writer.write(encoder.encode(content));
      } else {
        return writer.close();
      }
    },
    destroy(err) {
      console.log(err);
      writer.close();
    }
  });
}

initDirectivesForSSR();

export { pipeToNodeWritable, pipeToWebWritable, renderToNodeStream, renderToSimpleStream, renderToStream, renderToString, renderToWebStream, ssrGetDirectiveProps, ssrGetDynamicModelProps, ssrInterpolate, ssrLooseContain, ssrLooseEqual, ssrRenderAttr, ssrRenderAttrs, ssrRenderClass, ssrRenderComponent, ssrRenderDynamicAttr, ssrRenderDynamicModel, ssrRenderList, ssrRenderSlot, ssrRenderSlotInner, ssrRenderStyle, ssrRenderSuspense, ssrRenderTeleport, renderVNode as ssrRenderVNode };

license: mit


code:
'use strict'

if (process.env.NODE_ENV === 'production') {
  module.exports = require('./dist/server-renderer.cjs.prod.js')
} else {
  module.exports = require('./dist/server-renderer.cjs.js')
}


@vue/server-renderer

description: @vue/server-renderer

VueServerRenderer

formats: esm-bundler esm-browser cjs

type: git

directory: packages/server-renderer

author: Evan You

license: MIT


code:
# @vue/shared

Internal utility functions and constants shared across `@vue` packages.


code:
/**
 * Make a map and return a function for checking if a key
 * is in that map.
 * IMPORTANT: all calls of this function must be prefixed with
 * \/\*#\_\_PURE\_\_\*\/
 * So that rollup can tree-shake them if necessary.
 */
/*! #__NO_SIDE_EFFECTS__ */
export declare function makeMap(str: string, expectsLowerCase?: boolean): (key: string) => boolean;

export declare const EMPTY_OBJ: {
    readonly [key: string]: any;
};
export declare const EMPTY_ARR: readonly never[];
export declare const NOOP: () => void;
/**
 * Always return false.
 */
export declare const NO: () => boolean;
export declare const isOn: (key: string) => boolean;
export declare const isModelListener: (key: string) => boolean;
export declare const extend: {
    <T extends {}, U>(target: T, source: U): T & U;
    <T_1 extends {}, U_1, V>(target: T_1, source1: U_1, source2: V): T_1 & U_1 & V;
    <T_2 extends {}, U_2, V_1, W>(target: T_2, source1: U_2, source2: V_1, source3: W): T_2 & U_2 & V_1 & W;
    (target: object, ...sources: any[]): any;
};
export declare const remove: <T>(arr: T[], el: T) => void;
export declare const hasOwn: (val: object, key: string | symbol) => key is never;
export declare const isArray: (arg: any) => arg is any[];
export declare const isMap: (val: unknown) => val is Map<any, any>;
export declare const isSet: (val: unknown) => val is Set<any>;
export declare const isDate: (val: unknown) => val is Date;
export declare const isRegExp: (val: unknown) => val is RegExp;
export declare const isFunction: (val: unknown) => val is Function;
export declare const isString: (val: unknown) => val is string;
export declare const isSymbol: (val: unknown) => val is symbol;
export declare const isObject: (val: unknown) => val is Record<any, any>;
export declare const isPromise: <T = any>(val: unknown) => val is Promise<T>;
export declare const objectToString: () => string;
export declare const toTypeString: (value: unknown) => string;
export declare const toRawType: (value: unknown) => string;
export declare const isPlainObject: (val: unknown) => val is object;
export declare const isIntegerKey: (key: unknown) => boolean;
export declare const isReservedProp: (key: string) => boolean;
export declare const isBuiltInDirective: (key: string) => boolean;
/**
 * @private
 */
export declare const camelize: (str: string) => string;
/**
 * @private
 */
export declare const hyphenate: (str: string) => string;
/**
 * @private
 */
export declare const capitalize: <T extends string>(str: T) => Capitalize<T>;
/**
 * @private
 */
export declare const toHandlerKey: <T extends string>(str: T) => T extends "" ? "" : `on${Capitalize<T>}`;
export declare const hasChanged: (value: any, oldValue: any) => boolean;
export declare const invokeArrayFns: (fns: Function[], ...arg: any[]) => void;
export declare const def: (obj: object, key: string | symbol, value: any, writable?: boolean) => void;
/**
 * "123-foo" will be parsed to 123
 * This is used for the .number modifier in v-model
 */
export declare const looseToNumber: (val: any) => any;
/**
 * Only concerns number-like strings
 * "123-foo" will be returned as-is
 */
export declare const toNumber: (val: any) => any;
export declare const getGlobalThis: () => any;
export declare function genPropsAccessExp(name: string): string;

/**
 * Patch flags are optimization hints generated by the compiler.
 * when a block with dynamicChildren is encountered during diff, the algorithm
 * enters "optimized mode". In this mode, we know that the vdom is produced by
 * a render function generated by the compiler, so the algorithm only needs to
 * handle updates explicitly marked by these patch flags.
 *
 * Patch flags can be combined using the | bitwise operator and can be checked
 * using the & operator, e.g.
 *
 * ```js
 * const flag = TEXT | CLASS
 * if (flag & TEXT) { ... }
 * ```
 *
 * Check the `patchElement` function in '../../runtime-core/src/renderer.ts' to see how the
 * flags are handled during diff.
 */
export declare enum PatchFlags {
    /**
     * Indicates an element with dynamic textContent (children fast path)
     */
    TEXT = 1,
    /**
     * Indicates an element with dynamic class binding.
     */
    CLASS = 2,
    /**
     * Indicates an element with dynamic style
     * The compiler pre-compiles static string styles into static objects
     * + detects and hoists inline static objects
     * e.g. `style="color: red"` and `:style="{ color: 'red' }"` both get hoisted
     * as:
     * ```js
     * const style = { color: 'red' }
     * render() { return e('div', { style }) }
     * ```
     */
    STYLE = 4,
    /**
     * Indicates an element that has non-class/style dynamic props.
     * Can also be on a component that has any dynamic props (includes
     * class/style). when this flag is present, the vnode also has a dynamicProps
     * array that contains the keys of the props that may change so the runtime
     * can diff them faster (without having to worry about removed props)
     */
    PROPS = 8,
    /**
     * Indicates an element with props with dynamic keys. When keys change, a full
     * diff is always needed to remove the old key. This flag is mutually
     * exclusive with CLASS, STYLE and PROPS.
     */
    FULL_PROPS = 16,
    /**
     * Indicates an element that requires props hydration
     * (but not necessarily patching)
     * e.g. event listeners & v-bind with prop modifier
     */
    NEED_HYDRATION = 32,
    /**
     * Indicates a fragment whose children order doesn't change.
     */
    STABLE_FRAGMENT = 64,
    /**
     * Indicates a fragment with keyed or partially keyed children
     */
    KEYED_FRAGMENT = 128,
    /**
     * Indicates a fragment with unkeyed children.
     */
    UNKEYED_FRAGMENT = 256,
    /**
     * Indicates an element that only needs non-props patching, e.g. ref or
     * directives (onVnodeXXX hooks). since every patched vnode checks for refs
     * and onVnodeXXX hooks, it simply marks the vnode so that a parent block
     * will track it.
     */
    NEED_PATCH = 512,
    /**
     * Indicates a component with dynamic slots (e.g. slot that references a v-for
     * iterated value, or dynamic slot names).
     * Components with this flag are always force updated.
     */
    DYNAMIC_SLOTS = 1024,
    /**
     * Indicates a fragment that was created only because the user has placed
     * comments at the root level of a template. This is a dev-only flag since
     * comments are stripped in production.
     */
    DEV_ROOT_FRAGMENT = 2048,
    /**
     * SPECIAL FLAGS -------------------------------------------------------------
     * Special flags are negative integers. They are never matched against using
     * bitwise operators (bitwise matching should only happen in branches where
     * patchFlag > 0), and are mutually exclusive. When checking for a special
     * flag, simply check patchFlag === FLAG.
     */
    /**
     * Indicates a hoisted static vnode. This is a hint for hydration to skip
     * the entire sub tree since static content never needs to be updated.
     */
    HOISTED = -1,
    /**
     * A special flag that indicates that the diffing algorithm should bail out
     * of optimized mode. For example, on block fragments created by renderSlot()
     * when encountering non-compiler generated slots (i.e. manually written
     * render functions, which should always be fully diffed)
     * OR manually cloneVNodes
     */
    BAIL = -2
}
/**
 * dev only flag -> name mapping
 */
export declare const PatchFlagNames: Record<PatchFlags, string>;

export declare enum ShapeFlags {
    ELEMENT = 1,
    FUNCTIONAL_COMPONENT = 2,
    STATEFUL_COMPONENT = 4,
    TEXT_CHILDREN = 8,
    ARRAY_CHILDREN = 16,
    SLOTS_CHILDREN = 32,
    TELEPORT = 64,
    SUSPENSE = 128,
    COMPONENT_SHOULD_KEEP_ALIVE = 256,
    COMPONENT_KEPT_ALIVE = 512,
    COMPONENT = 6
}

export declare enum SlotFlags {
    /**
     * Stable slots that only reference slot props or context state. The slot
     * can fully capture its own dependencies so when passed down the parent won't
     * need to force the child to update.
     */
    STABLE = 1,
    /**
     * Slots that reference scope variables (v-for or an outer slot prop), or
     * has conditional structure (v-if, v-for). The parent will need to force
     * the child to update because the slot does not fully capture its dependencies.
     */
    DYNAMIC = 2,
    /**
     * `<slot/>` being forwarded into a child component. Whether the parent needs
     * to update the child is dependent on what kind of slots the parent itself
     * received. This has to be refined at runtime, when the child's vnode
     * is being created (in `normalizeChildren`)
     */
    FORWARDED = 3
}
/**
 * Dev only
 */
export declare const slotFlagsText: {
    1: string;
    2: string;
    3: string;
};

export declare const isGloballyAllowed: (key: string) => boolean;
/** @deprecated use `isGloballyAllowed` instead */
export declare const isGloballyWhitelisted: (key: string) => boolean;

export declare function generateCodeFrame(source: string, start?: number, end?: number): string;

export type NormalizedStyle = Record<string, string | number>;
export declare function normalizeStyle(value: unknown): NormalizedStyle | string | undefined;
export declare function parseStringStyle(cssText: string): NormalizedStyle;
export declare function stringifyStyle(styles: NormalizedStyle | string | undefined): string;
export declare function normalizeClass(value: unknown): string;
export declare function normalizeProps(props: Record<string, any> | null): Record<string, any> | null;

/**
 * Compiler only.
 * Do NOT use in runtime code paths unless behind `__DEV__` flag.
 */
export declare const isHTMLTag: (key: string) => boolean;
/**
 * Compiler only.
 * Do NOT use in runtime code paths unless behind `__DEV__` flag.
 */
export declare const isSVGTag: (key: string) => boolean;
/**
 * Compiler only.
 * Do NOT use in runtime code paths unless behind `__DEV__` flag.
 */
export declare const isMathMLTag: (key: string) => boolean;
/**
 * Compiler only.
 * Do NOT use in runtime code paths unless behind `__DEV__` flag.
 */
export declare const isVoidTag: (key: string) => boolean;

export declare const isSpecialBooleanAttr: (key: string) => boolean;
/**
 * The full list is needed during SSR to produce the correct initial markup.
 */
export declare const isBooleanAttr: (key: string) => boolean;
/**
 * Boolean attributes should be included if the value is truthy or ''.
 * e.g. `<select multiple>` compiles to `{ multiple: '' }`
 */
export declare function includeBooleanAttr(value: unknown): boolean;
export declare function isSSRSafeAttrName(name: string): boolean;
export declare const propsToAttrMap: Record<string, string | undefined>;
/**
 * Known attributes, this is used for stringification of runtime static nodes
 * so that we don't stringify bindings that cannot be set from HTML.
 * Don't also forget to allow `data-*` and `aria-*`!
 * Generated from https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
 */
export declare const isKnownHtmlAttr: (key: string) => boolean;
/**
 * Generated from https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute
 */
export declare const isKnownSvgAttr: (key: string) => boolean;
/**
 * Shared between server-renderer and runtime-core hydration logic
 */
export declare function isRenderableAttrValue(value: unknown): boolean;

export declare function escapeHtml(string: unknown): string;
export declare function escapeHtmlComment(src: string): string;

export declare function looseEqual(a: any, b: any): boolean;
export declare function looseIndexOf(arr: any[], val: any): number;

/**
 * For converting {{ interpolation }} values to displayed strings.
 * @private
 */
export declare const toDisplayString: (val: unknown) => string;

export type Prettify<T> = {
    [K in keyof T]: T[K];
} & {};
export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
export type LooseRequired<T> = {
    [P in keyof (T & Required<T>)]: T[P];
};
export type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N;
export type Awaited<T> = T extends null | undefined ? T : T extends object & {
    then(onfulfilled: infer F, ...args: infer _): any;
} ? F extends (value: infer V, ...args: infer _) => any ? Awaited<V> : never : T;


code:
'use strict'

if (process.env.NODE_ENV === 'production') {
  module.exports = require('./dist/shared.cjs.prod.js')
} else {
  module.exports = require('./dist/shared.cjs.js')
}


@vue/shared

description: internal utils shared across @vue packages

formats: esm-bundler cjs

directory: packages/shared


code:
module.exports = {
  root: true,
  extends: ['plugin:vue-libs/recommended'],
  rules: {
    indent: 'off',
    'space-before-function-paren': 'off'
  }
}


code:
# [15.11.0](https://github.com/vuejs/vue-loader/compare/v15.10.2...v15.11.0) (2023-10-18)

### Features

* A new `experimentalInlineMatchResource` option (webpack 5 only), which leverages webpack 5's [inline matchResource](https://webpack.js.org/api/loaders/#inline-matchresource) feature in the underlying implementation, and works well with the [`experiments.css`](https://webpack.js.org/configuration/experiments/#experimentscss) feature. This also makes `vue-loader` compatible with [Rspack](https://www.rspack.dev/guide/vue). ([#2058](https://github.com/vuejs/vue-loader/pull/2058))

# [15.10.2](https://github.com/vuejs/vue-loader/compare/v15.10.1...v15.10.2) (2023-08-23)

### Bug Fixes

* don't enable prettify by default if prettier 3 is detected ([aa2558d](https://github.com/vuejs/vue-loader/commit/aa2558d))

# [15.10.1](https://github.com/vuejs/vue-loader/compare/v15.10.0...v15.10.1) (2022-11-14)

### Bug Fixes

* skip thread-loader when cloning js rules to template compilation pipeline, fixes <https://github.com/vuejs/vue/issues/12828> ([fb6ff6e](https://github.com/vuejs/vue-loader/commit/fb6ff6e))

# [15.10.0](https://github.com/vuejs/vue-loader/compare/v15.10.0-beta.6...v15.10.0) (2022-07-01)

# [15.10.0-beta.6](https://github.com/vuejs/vue-loader/compare/v15.10.0-beta.5...v15.10.0-beta.6) (2022-06-20)

### Bug Fixes

* always pass id to stylePostLoader when possible ([364ad09](https://github.com/vuejs/vue-loader/commit/364ad09))

# [15.10.0-beta.5](https://github.com/vuejs/vue-loader/compare/v15.10.0-beta.4...v15.10.0-beta.5) (2022-06-20)

### Bug Fixes

* css v-bind in production mode ([655e5f8](https://github.com/vuejs/vue-loader/commit/655e5f8))

# [15.10.0-beta.4](https://github.com/vuejs/vue-loader/compare/v15.10.0-beta.3...v15.10.0-beta.4) (2022-06-20)

### Features

* support css v-bind (requires 2.7.0-beta.3) ([d653f3b](https://github.com/vuejs/vue-loader/commit/d653f3b))

# [15.10.0-beta.3](https://github.com/vuejs/vue-loader/compare/v15.10.0-beta.2...v15.10.0-beta.3) (2022-06-16)

### Bug Fixes

* cache descriptor with correct resource path ([f6c83b5](https://github.com/vuejs/vue-loader/commit/f6c83b5))

# [15.10.0-beta.2](https://github.com/vuejs/vue-loader/compare/v15.10.0-beta.1...v15.10.0-beta.2) (2022-06-16)

### Features

* use script-analyzed bindings when compiling template ([55de28c](https://github.com/vuejs/vue-loader/commit/55de28c))

# [15.10.0-beta.1](https://github.com/vuejs/vue-loader/compare/v15.9.8...v15.10.0-beta.1) (2022-06-14)

### Features

* apply js loaders to compiled template code when used with 2.7 ([30464a8](https://github.com/vuejs/vue-loader/commit/30464a8))
* compat for vue 2.7, support `<script setup>` ([308715a](https://github.com/vuejs/vue-loader/commit/308715a))

## [15.9.8](https://github.com/vuejs/vue-loader/compare/v15.9.7...v15.9.8) (2021-08-02)

### Bug Fixes

* fix webpack 5.48 compatibility ([c4c5f17](https://github.com/vuejs/vue-loader/commit/c4c5f17)), closes [#1859](https://github.com/vuejs/vue-loader/issues/1859)

## [15.9.7](https://github.com/vuejs/vue-loader/compare/v15.9.6...v15.9.7) (2021-05-11)

### Bug Fixes

* [plugin] Use compiler.webpack when possible ([#1822](https://github.com/vuejs/vue-loader/issues/1822)) ([f7ee30b](https://github.com/vuejs/vue-loader/commit/f7ee30b)), closes [#1781](https://github.com/vuejs/vue-loader/issues/1781)
* check for compiler.webpack existence ([2472b2f](https://github.com/vuejs/vue-loader/commit/2472b2f))

## [15.9.6](https://github.com/vuejs/vue-loader/compare/v15.9.5...v15.9.6) (2020-12-17)

### Bug Fixes

* resourceQuery could be undefined in webpack 5 ([a2b89d3](https://github.com/vuejs/vue-loader/commit/a2b89d3)), closes [#1771](https://github.com/vuejs/vue-loader/issues/1771)

## [15.9.5](https://github.com/vuejs/vue-loader/compare/v15.9.4...v15.9.5) (2020-11-02)

### Bug Fixes

* add rule plugins to keep up with webpack 5 new features ([7ca8e2c](https://github.com/vuejs/vue-loader/commit/7ca8e2c))
* ensure new webpack5 generator property in rules passes ruleset checks ([#1753](https://github.com/vuejs/vue-loader/issues/1753)) ([f79bb08](https://github.com/vuejs/vue-loader/commit/f79bb08)), closes [#1729](https://github.com/vuejs/vue-loader/issues/1729)

## [15.9.4](https://github.com/vuejs/vue-loader/compare/v15.9.3...v15.9.4) (2020-10-27)

### Bug Fixes

* fix id differences between different operating systems ([#1706](https://github.com/vuejs/vue-loader/issues/1706)) ([afe8a0d](https://github.com/vuejs/vue-loader/commit/afe8a0d))
* fix mini-css-extract-plugin missing default export error ([#1748](https://github.com/vuejs/vue-loader/issues/1748)) ([429a284](https://github.com/vuejs/vue-loader/commit/429a284))

## [15.9.3](https://github.com/vuejs/vue-loader/compare/v15.9.2...v15.9.3) (2020-06-23)

### Bug Fixes

* skip matching rule with 'enforce' ([e7b2b11](https://github.com/vuejs/vue-loader/commit/e7b2b11)), closes [#1680](https://github.com/vuejs/vue-loader/issues/1680)

## [15.9.2](https://github.com/vuejs/vue-loader/compare/v15.9.1...v15.9.2) (2020-05-01)

### Bug Fixes

* fix getting shadow root when component is functional ([#1560](https://github.com/vuejs/vue-loader/issues/1560)) ([9a7357a](https://github.com/vuejs/vue-loader/commit/9a7357a))

### Documentation

* add DocSearch as recommended by vuepress ([#1662](https://github.com/vuejs/vue-loader/issues/1662)) ([032d56b](https://github.com/vuejs/vue-loader/commit/032d56b))

## [15.9.1](https://github.com/vuejs/vue-loader/compare/v15.9.0...v15.9.1) (2020-03-19)

### Bug Fixes

* ensure unique `ident` when cloning rules, fix webpack 5 compatibility ([#1653](https://github.com/vuejs/vue-loader/issues/1653)) ([84c34a4](https://github.com/vuejs/vue-loader/commit/84c34a4))

# [15.9.0](https://github.com/vuejs/vue-loader/compare/v15.8.3...v15.9.0) (2020-02-12)

### Bug Fixes

* add vue-template-compiler as an optional peer dependency ([56db1d7](https://github.com/vuejs/vue-loader/commit/56db1d7)), closes [#1639](https://github.com/vuejs/vue-loader/issues/1639)

### Features

* support Rule.rules (nested rules) ([#1618](https://github.com/vuejs/vue-loader/issues/1618)) ([5943319](https://github.com/vuejs/vue-loader/commit/5943319))

## [15.8.3](https://github.com/vuejs/vue-loader/compare/v15.8.2...v15.8.3) (2019-12-16)

## [15.8.2](https://github.com/vuejs/vue-loader/compare/v15.8.1...v15.8.2) (2019-12-16)

### Bug Fixes

* fix compatibility with webpack 3 ([745d054](https://github.com/vuejs/vue-loader/commit/745d054))

# [15.8.0](https://github.com/vuejs/vue-loader/compare/v15.7.2...v15.8.0) (2019-12-16)

### Bug Fixes

* **types:** should import type definition from the `dist` folder ([0751213](https://github.com/vuejs/vue-loader/commit/0751213))

### Features

* add support for webpack5 ([#1613](https://github.com/vuejs/vue-loader/issues/1613)) ([59eebca](https://github.com/vuejs/vue-loader/commit/59eebca))

## [15.7.2](https://github.com/vuejs/vue-loader/compare/v15.7.1...v15.7.2) (2019-11-02)

### Bug Fixes

* add cache-loader to optional peer dependency ([e9d8b71](https://github.com/vuejs/vue-loader/commit/e9d8b71))
* use `require.resolve` when referencing `cache-loader` ([#1585](https://github.com/vuejs/vue-loader/issues/1585)) ([d3fa467](https://github.com/vuejs/vue-loader/commit/d3fa467))

## [15.7.1](https://github.com/vuejs/vue-loader/compare/v15.7.0...v15.7.1) (2019-07-18)

### Bug Fixes

* use "api.isRecorded" instead of "module.hot.data" ([#1569](https://github.com/vuejs/vue-loader/issues/1569)) ([6a05115](https://github.com/vuejs/vue-loader/commit/6a05115))

# [15.7.0](https://github.com/vuejs/vue-loader/compare/v15.6.4...v15.7.0) (2019-02-28)

### Features

* support post loaders for template blocks ([#1500](https://github.com/vuejs/vue-loader/issues/1500)) ([731a7ad](https://github.com/vuejs/vue-loader/commit/731a7ad))

## [15.6.4](https://github.com/vuejs/vue-loader/compare/v15.6.0...v15.6.4) (2019-02-19)

### Bug Fixes

* **templateLoder:** honor options.productionMode ([#1409](https://github.com/vuejs/vue-loader/issues/1409)) ([01990d0](https://github.com/vuejs/vue-loader/commit/01990d0))
* avoid generating custom block when there is only cache-loader ([#1493](https://github.com/vuejs/vue-loader/issues/1493)) ([a1af343](https://github.com/vuejs/vue-loader/commit/a1af343))
* fix wrong outputSourceRange usage ([#1482](https://github.com/vuejs/vue-loader/issues/1482)) ([2d96215](https://github.com/vuejs/vue-loader/commit/2d96215))
* keep style index consistent when filtering styles ([#1496](https://github.com/vuejs/vue-loader/issues/1496)) ([e02d937](https://github.com/vuejs/vue-loader/commit/e02d937))
* relay correct error message on vue-template-compiler version mismatch ([fdd0338](https://github.com/vuejs/vue-loader/commit/fdd0338))

## [15.6.3](https://github.com/vuejs/vue-loader/compare/v15.6.2...v15.6.3) (2019-02-18)

### Bug Fixes

* **templateLoder:** honor options.productionMode ([#1409](https://github.com/vuejs/vue-loader/issues/1409)) ([01990d0](https://github.com/vuejs/vue-loader/commit/01990d0))
* avoid generating custom block when there is only cache-loader ([#1493](https://github.com/vuejs/vue-loader/issues/1493)) ([a1af343](https://github.com/vuejs/vue-loader/commit/a1af343))

## [15.6.2](https://github.com/vuejs/vue-loader/compare/v15.6.1...v15.6.2) (2019-01-27)

### Bug Fixes

* fix wrong outputSourceRange usage ([#1482](https://github.com/vuejs/vue-loader/issues/1482)) ([2d96215](https://github.com/vuejs/vue-loader/commit/2d96215))

## [15.6.1](https://github.com/vuejs/vue-loader/compare/v15.6.0...v15.6.1) (2019-01-25)

### Bug Fixes

* relay correct error message on vue-template-compiler version mismatch ([fdd0338](https://github.com/vuejs/vue-loader/commit/fdd0338))

# [15.6.0](https://github.com/vuejs/vue-loader/compare/v15.5.1...v15.6.0) (2019-01-23)

### Bug Fixes

* template comments replace windows \ to / confirm consistent hash ([#1477](https://github.com/vuejs/vue-loader/issues/1477)) ([adc6dd6](https://github.com/vuejs/vue-loader/commit/adc6dd6))

### Features

* make `__file` injection opt-in in production ([#1475](https://github.com/vuejs/vue-loader/issues/1475)) ([001382d](https://github.com/vuejs/vue-loader/commit/001382d))
* support for compiler 2.6 outputSourceRange ([2215585](https://github.com/vuejs/vue-loader/commit/2215585))
* support webpack 5 hooks ([#1469](https://github.com/vuejs/vue-loader/issues/1469)) ([7275ae4](https://github.com/vuejs/vue-loader/commit/7275ae4))

## [15.5.1](https://github.com/vuejs/vue-loader/compare/v15.5.0...v15.5.1) (2019-01-08)

### Bug Fixes

* avoid to generate empty css chunk files ([#1464](https://github.com/vuejs/vue-loader/issues/1464)) ([c444ab6](https://github.com/vuejs/vue-loader/commit/c444ab6))

# [15.5.0](https://github.com/vuejs/vue-loader/compare/v15.4.0...v15.5.0) (2019-01-04)

### Bug Fixes

* css modules extends error ([#1452](https://github.com/vuejs/vue-loader/issues/1452)) ([082c6ea](https://github.com/vuejs/vue-loader/commit/082c6ea)), closes [#1449](https://github.com/vuejs/vue-loader/issues/1449)
* hide ext appending behind a flag (ref [#1372](https://github.com/vuejs/vue-loader/issues/1372)) ([f0beed3](https://github.com/vuejs/vue-loader/commit/f0beed3))
* include query in loader dedupe ([4a894de](https://github.com/vuejs/vue-loader/commit/4a894de)), closes [vue-cli#2451](https://github.com/vue-cli/issues/2451)

### Features

* add `prettify` option ([#1461](https://github.com/vuejs/vue-loader/issues/1461)) ([62a9155](https://github.com/vuejs/vue-loader/commit/62a9155)), closes [#1426](https://github.com/vuejs/vue-loader/issues/1426)

## [15.4.2](https://github.com/vuejs/vue-loader/compare/v15.4.1...v15.4.2) (2018-09-11)

### Bug Fixes

* include query in loader dedupe ([4a894de](https://github.com/vuejs/vue-loader/commit/4a894de)), closes [vue-cli#2451](https://github.com/vue-cli/issues/2451)

## [15.4.1](https://github.com/vuejs/vue-loader/compare/v15.4.0...v15.4.1) (2018-08-26)

### Bug Fixes

* hide ext appending behind a flag (ref [#1372](https://github.com/vuejs/vue-loader/issues/1372)) ([f0beed3](https://github.com/vuejs/vue-loader/commit/f0beed3))

# [15.4.0](https://github.com/vuejs/vue-loader/compare/v15.3.0...v15.4.0) (2018-08-20)

### Bug Fixes

* fix inconsistent path between Windows and POSIX systems ( ([#1384](https://github.com/vuejs/vue-loader/issues/1384) ([74a7dbd](https://github.com/vuejs/vue-loader/commit/74a7dbd))

### Features

* append the file extension to the mapping files in devtools ([#1372](https://github.com/vuejs/vue-loader/issues/1372)) ([0c2da0f](https://github.com/vuejs/vue-loader/commit/0c2da0f)), closes [#1371](https://github.com/vuejs/vue-loader/issues/1371)

# [15.3.0](https://github.com/vuejs/vue-loader/compare/v15.2.7...v15.3.0) (2018-08-07)

### Bug Fixes

* avoid absolute path in cache-loader inline options ([c6ab50a](https://github.com/vuejs/vue-loader/commit/c6ab50a)), closes [#1367](https://github.com/vuejs/vue-loader/issues/1367)

### Features

* set file basename to __file in production ([#1368](https://github.com/vuejs/vue-loader/issues/1368)) ([2f441b9](https://github.com/vuejs/vue-loader/commit/2f441b9))

## [15.2.7](https://github.com/vuejs/vue-loader/compare/v15.2.6...v15.2.7) (2018-08-07)

## [15.2.6](https://github.com/vuejs/vue-loader/compare/v15.2.5...v15.2.6) (2018-07-18)

### Bug Fixes

* ensure consistent component id on different OS ([0766fe7](https://github.com/vuejs/vue-loader/commit/0766fe7)), closes [vuejs/vue-cli#1728](https://github.com/vuejs/vue-cli/issues/1728)

## [15.2.5](https://github.com/vuejs/vue-loader/compare/v15.2.4...v15.2.5) (2018-07-17)

### Bug Fixes

* ensure same compiler is used for both parse and tempalte compilation ([1bfc08a](https://github.com/vuejs/vue-loader/commit/1bfc08a))
* should not remove eslint-loader on src import blocks (close [#1359](https://github.com/vuejs/vue-loader/issues/1359)) ([6f1d404](https://github.com/vuejs/vue-loader/commit/6f1d404))
* support usage with other loaders with enforce: post ([be2384c](https://github.com/vuejs/vue-loader/commit/be2384c)), closes [#1351](https://github.com/vuejs/vue-loader/issues/1351)

### Features

* inherit root request query in custom block loaders ([#1330](https://github.com/vuejs/vue-loader/issues/1330)) ([0f0b09b](https://github.com/vuejs/vue-loader/commit/0f0b09b))

## [15.2.4](https://github.com/vuejs/vue-loader/compare/v15.2.2...v15.2.4) (2018-06-01)

### Bug Fixes

* ensure plugin error is emitted only once ([0b006a3](https://github.com/vuejs/vue-loader/commit/0b006a3))
* fix unexpected error when options of cache-loader contains ! ([#1334](https://github.com/vuejs/vue-loader/issues/1334)) ([c4a2719](https://github.com/vuejs/vue-loader/commit/c4a2719))
* use constant plugin NS ([0fb5172](https://github.com/vuejs/vue-loader/commit/0fb5172)), closes [#1331](https://github.com/vuejs/vue-loader/issues/1331)

### Features

* inject issuerPath to resourceQuery for custom block src imports ([#1313](https://github.com/vuejs/vue-loader/issues/1313)) ([a004e30](https://github.com/vuejs/vue-loader/commit/a004e30))

## [15.2.3](https://github.com/vuejs/vue-loader/compare/v15.2.2...v15.2.3) (2018-06-01)

### Bug Fixes

* ensure plugin error is emitted only once ([0b006a3](https://github.com/vuejs/vue-loader/commit/0b006a3))
* use constant plugin NS ([0fb5172](https://github.com/vuejs/vue-loader/commit/0fb5172)), closes [#1331](https://github.com/vuejs/vue-loader/issues/1331)

### Features

* inject issuerPath to resourceQuery for custom block src imports ([#1313](https://github.com/vuejs/vue-loader/issues/1313)) ([a004e30](https://github.com/vuejs/vue-loader/commit/a004e30))

## [15.2.2](https://github.com/vuejs/vue-loader/compare/v15.2.0...v15.2.2) (2018-05-28)

### Bug Fixes

* check loader for cnpm(npminstall) ([#1321](https://github.com/vuejs/vue-loader/issues/1321)) ([37fbaeb](https://github.com/vuejs/vue-loader/commit/37fbaeb))
* ensure template cache uses unique identifier ([538198e](https://github.com/vuejs/vue-loader/commit/538198e))

## [15.2.1](https://github.com/vuejs/vue-loader/compare/v15.2.0...v15.2.1) (2018-05-25)

### Bug Fixes

* ensure template cache uses unique identifier ([bdb13be](https://github.com/vuejs/vue-loader/commit/bdb13be))

# [15.2.0](https://github.com/vuejs/vue-loader/compare/v15.1.0...v15.2.0) (2018-05-22)

### Features

* enable template compile caching ([28e0fd3](https://github.com/vuejs/vue-loader/commit/28e0fd3))

# [15.1.0](https://github.com/vuejs/vue-loader/compare/v15.0.12...v15.1.0) (2018-05-19)

### Performance Improvements

* avoid duplicate linting when used with eslint-loader ([3d07f81](https://github.com/vuejs/vue-loader/commit/3d07f81))

## [15.0.12](https://github.com/vuejs/vue-loader/compare/v15.0.11...v15.0.12) (2018-05-18)

### Bug Fixes

* ignore attrs that might interfere with query generation ([3a37269](https://github.com/vuejs/vue-loader/commit/3a37269)), closes [vuejs/vue-cli#1324](https://github.com/vuejs/vue-cli/issues/1324)

## [15.0.11](https://github.com/vuejs/vue-loader/compare/v15.0.9...v15.0.11) (2018-05-15)

### Bug Fixes

* improve HMR reliability ([4ccd96f](https://github.com/vuejs/vue-loader/commit/4ccd96f))

## [15.0.10](https://github.com/vuejs/vue-loader/compare/v15.0.9...v15.0.10) (2018-05-11)

### Bug Fixes

* improve HMR reliability ([52012cd](https://github.com/vuejs/vue-loader/commit/52012cd))

## [15.0.9](https://github.com/vuejs/vue-loader/compare/v15.0.8...v15.0.9) (2018-05-04)

### Bug Fixes

* shadowMode still has to be an option ([4529f83](https://github.com/vuejs/vue-loader/commit/4529f83))

## [15.0.8](https://github.com/vuejs/vue-loader/compare/v15.0.7...v15.0.8) (2018-05-04)

### Bug Fixes

* avoid mutating original rules array ([14bfc01](https://github.com/vuejs/vue-loader/commit/14bfc01)), closes [#1286](https://github.com/vuejs/vue-loader/issues/1286)

## [15.0.7](https://github.com/vuejs/vue-loader/compare/v15.0.6...v15.0.7) (2018-05-03)

### Bug Fixes

* stylePostLoader injection for windows flat node_modules ([a9a4412](https://github.com/vuejs/vue-loader/commit/a9a4412)), closes [#1284](https://github.com/vuejs/vue-loader/issues/1284)

## [15.0.6](https://github.com/vuejs/vue-loader/compare/v15.0.5...v15.0.6) (2018-05-02)

### Bug Fixes

* duplicate loaders when using src import with loader options ([37329e1](https://github.com/vuejs/vue-loader/commit/37329e1)), closes [#1278](https://github.com/vuejs/vue-loader/issues/1278)

## [15.0.5](https://github.com/vuejs/vue-loader/compare/v15.0.4...v15.0.5) (2018-04-30)

### Bug Fixes

* ignore VueLoaderPlugin check when using thread-loader ([#1268](https://github.com/vuejs/vue-loader/issues/1268)) ([476f466](https://github.com/vuejs/vue-loader/commit/476f466)), closes [#1267](https://github.com/vuejs/vue-loader/issues/1267)

## [15.0.4](https://github.com/vuejs/vue-loader/compare/v15.0.3...v15.0.4) (2018-04-27)

### Bug Fixes

* enable whitelist in exclude function ([5b0e392](https://github.com/vuejs/vue-loader/commit/5b0e392))

## [15.0.3](https://github.com/vuejs/vue-loader/compare/v15.0.2...v15.0.3) (2018-04-26)

### Bug Fixes

* handle rule.use being a string (ref: [#1256](https://github.com/vuejs/vue-loader/issues/1256)) ([fc2ba27](https://github.com/vuejs/vue-loader/commit/fc2ba27))

## [15.0.2](https://github.com/vuejs/vue-loader/compare/v15.0.1...v15.0.2) (2018-04-26)

### Bug Fixes

* remove resource field in cloned rules (fix [#1254](https://github.com/vuejs/vue-loader/issues/1254)) ([35ca03f](https://github.com/vuejs/vue-loader/commit/35ca03f))

## [15.0.1](https://github.com/vuejs/vue-loader/compare/v15.0.0...v15.0.1) (2018-04-25)

### Bug Fixes

* prioritize .vue rules in plugin (fix [#1246](https://github.com/vuejs/vue-loader/issues/1246)) ([bffacd5](https://github.com/vuejs/vue-loader/commit/bffacd5))
* warn missing plugin ([068bb81](https://github.com/vuejs/vue-loader/commit/068bb81))

# [15.0.0](https://github.com/vuejs/vue-loader/compare/v15.0.0-rc.2...v15.0.0) (2018-04-24)

### Bug Fixes

* compat with null-loader (close [#1239](https://github.com/vuejs/vue-loader/issues/1239)) ([5cd5f6f](https://github.com/vuejs/vue-loader/commit/5cd5f6f))

### Features

* support declaring rules using .vue.html (ref [#1238](https://github.com/vuejs/vue-loader/issues/1238)) ([a3af6b3](https://github.com/vuejs/vue-loader/commit/a3af6b3))

# [15.0.0-rc.2](https://github.com/vuejs/vue-loader/compare/v15.0.0-rc.1...v15.0.0-rc.2) (2018-04-11)

### Bug Fixes

* avoid bailout of webpack module concatenation ([#1230](https://github.com/vuejs/vue-loader/issues/1230)) ([b983304](https://github.com/vuejs/vue-loader/commit/b983304))
* reuse ident of css related loaders to avoid duplicates ([#1233](https://github.com/vuejs/vue-loader/issues/1233)) ([b16311f](https://github.com/vuejs/vue-loader/commit/b16311f))

# [15.0.0-rc.1](https://github.com/vuejs/vue-loader/compare/v15.0.0-beta.7...v15.0.0-rc.1) (2018-04-06)

### Features

* support being used on files not ending with .vue ([5a9ee91](https://github.com/vuejs/vue-loader/commit/5a9ee91))

# [15.0.0-beta.7](https://github.com/vuejs/vue-loader/compare/v15.0.0-beta.6...v15.0.0-beta.7) (2018-03-25)

### Features

* handle `<template lang="xxx">` with loaders ([c954f32](https://github.com/vuejs/vue-loader/commit/c954f32))

### BREAKING CHANGES

* `<template lang="xxx">` are now handled
with webpack loaders as well.

# [15.0.0-beta.6](https://github.com/vuejs/vue-loader/compare/v15.0.0-beta.5...v15.0.0-beta.6) (2018-03-24)

### Bug Fixes

* compat with html-webpack-plugin ([8626739](https://github.com/vuejs/vue-loader/commit/8626739)), closes [#1213](https://github.com/vuejs/vue-loader/issues/1213)
* only reuse ident for whitelisted loaders ([230abd4](https://github.com/vuejs/vue-loader/commit/230abd4)), closes [#1214](https://github.com/vuejs/vue-loader/issues/1214)

# [15.0.0-beta.5](https://github.com/vuejs/vue-loader/compare/v15.0.0-beta.4...v15.0.0-beta.5) (2018-03-23)

### Bug Fixes

* pass correct args to RuleSet.normalizeRule (fix [#1210](https://github.com/vuejs/vue-loader/issues/1210)) ([1c54dc4](https://github.com/vuejs/vue-loader/commit/1c54dc4))

# [15.0.0-beta.4](https://github.com/vuejs/vue-loader/compare/v15.0.0-beta.3...v15.0.0-beta.4) (2018-03-23)

### Bug Fixes

* avoid babel options validation error (fix [#1209](https://github.com/vuejs/vue-loader/issues/1209)) ([d3e3f5e](https://github.com/vuejs/vue-loader/commit/d3e3f5e))

# [15.0.0-beta.3](https://github.com/vuejs/vue-loader/compare/v15.0.0-beta.2...v15.0.0-beta.3) (2018-03-23)

### Bug Fixes

* handle vue rule with include (fix [#1201](https://github.com/vuejs/vue-loader/issues/1201)) ([2be5507](https://github.com/vuejs/vue-loader/commit/2be5507))
* make sure cloned rules reuse the exact same ident in options ([eab9460](https://github.com/vuejs/vue-loader/commit/eab9460)), closes [#1199](https://github.com/vuejs/vue-loader/issues/1199)
* remove rule.loaders from normalized rules ([#1207](https://github.com/vuejs/vue-loader/issues/1207)) ([e9cbbcd](https://github.com/vuejs/vue-loader/commit/e9cbbcd))
* support test-less oneOf rules ([7208885](https://github.com/vuejs/vue-loader/commit/7208885))
* use relative path for self path resolution ([343b9df](https://github.com/vuejs/vue-loader/commit/343b9df))

### Features

* **loader:** support options.productionMode ([#1208](https://github.com/vuejs/vue-loader/issues/1208)) ([69bc1c1](https://github.com/vuejs/vue-loader/commit/69bc1c1))

# [15.0.0-beta.2](https://github.com/vuejs/vue-loader/compare/v15.0.0-beta.1...v15.0.0-beta.2) (2018-03-22)

### Bug Fixes

* loader check for windows ([ab067b0](https://github.com/vuejs/vue-loader/commit/ab067b0))
* properly stringify hot-reload-api path for Windows ([fb1306e](https://github.com/vuejs/vue-loader/commit/fb1306e))

# [15.0.0-beta.1](https://github.com/vuejs/vue-loader/compare/f418bd9...v15.0.0-beta.1) (2018-03-21)

### Bug Fixes

* remove .vue from fake resourcePath to avoid double match ([7c5b6ac](https://github.com/vuejs/vue-loader/commit/7c5b6ac))

### Features

* basic hot reload ([f418bd9](https://github.com/vuejs/vue-loader/commit/f418bd9))
* css modules + hmr ([99754c0](https://github.com/vuejs/vue-loader/commit/99754c0))
* dynamic style injection ([234d48b](https://github.com/vuejs/vue-loader/commit/234d48b))
* expose all block attrs via query ([cda1ec3](https://github.com/vuejs/vue-loader/commit/cda1ec3))
* respect user compiler / compilerOptions ([58239f6](https://github.com/vuejs/vue-loader/commit/58239f6))
* support configuring loader for custom blocks via resourceQuery ([d04f9cf](https://github.com/vuejs/vue-loader/commit/d04f9cf))
* support rules with oneOf ([c3b379d](https://github.com/vuejs/vue-loader/commit/c3b379d))


code:
# vue-loader [![Build Status](https://circleci.com/gh/vuejs/vue-loader/tree/master.svg?style=shield)](https://circleci.com/gh/vuejs/vue-loader/tree/master) [![Windows Build status](https://ci.appveyor.com/api/projects/status/8cdonrkbg6m4k1tm/branch/master?svg=true)](https://ci.appveyor.com/project/yyx990803/vue-loader/branch/master)

> webpack loader for Vue Single-File Components

**NOTE:** The master branch now hosts the code for v15! Legacy code is now in the [v14 branch](https://github.com/vuejs/vue-loader/tree/v14).

- [Documentation](https://vue-loader.vuejs.org)
- [Migrating from v14](https://vue-loader.vuejs.org/migrating.html)

## What is Vue Loader?

`vue-loader` is a loader for [webpack](https://webpack.js.org/) that allows you to author Vue components in a format called [Single-File Components (SFCs)](./docs/spec.md):

``` vue
<template>
  <div class="example">{{ msg }}</div>
</template>

<script>
export default {
  data () {
    return {
      msg: 'Hello world!'
    }
  }
}
</script>

<style>
.example {
  color: red;
}
</style>
```

There are many cool features provided by `vue-loader`:

- Allows using other webpack loaders for each part of a Vue component, for example Sass for `<style>` and Pug for `<template>`;
- Allows custom blocks in a `.vue` file that can have custom loader chains applied to them;
- Treat static assets referenced in `<style>` and `<template>` as module dependencies and handle them with webpack loaders;
- Simulate scoped CSS for each component;
- State-preserving hot-reloading during development.

In a nutshell, the combination of webpack and `vue-loader` gives you a modern, flexible and extremely powerful front-end workflow for authoring Vue.js applications.

## How It Works

> The following section is for maintainers and contributors who are interested in the internal implementation details of `vue-loader`, and is **not** required knowledge for end users.

`vue-loader` is not a simple source transform loader. It handles each language blocks inside an SFC with its own dedicated loader chain (you can think of each block as a "virtual module"), and finally assembles the blocks together into the final module. Here's a brief overview of how the whole thing works:

1. `vue-loader` parses the SFC source code into an *SFC Descriptor* using `@vue/component-compiler-utils`. It then generates an import for each language block so the actual returned module code looks like this:

    ``` js
    // code returned from the main loader for 'source.vue'

    // import the <template> block
    import render from 'source.vue?vue&type=template'
    // import the <script> block
    import script from 'source.vue?vue&type=script'
    export * from 'source.vue?vue&type=script'
    // import <style> blocks
    import 'source.vue?vue&type=style&index=1'

    script.render = render
    export default script
    ```

    Notice how the code is importing `source.vue` itself, but with different request queries for each block.

2. We want the content in `script` block to be treated like `.js` files (and if it's `<script lang="ts">`, we want to to be treated like `.ts` files). Same for other language blocks. So we want webpack to apply any configured module rules that matches `.js` also to requests that look like `source.vue?vue&type=script`. This is what `VueLoaderPlugin` (`src/plugins.ts`) does: for each module rule in the webpack config, it creates a modified clone that targets corresponding Vue language block requests.

    Suppose we have configured `babel-loader` for all `*.js` files. That rule will be cloned and applied to Vue SFC `<script>` blocks as well. Internally to webpack, a request like

    ``` js
    import script from 'source.vue?vue&type=script'
    ```

    Will expand to:

    ``` js
    import script from 'babel-loader!vue-loader!source.vue?vue&type=script'
    ```

    Notice the `vue-loader` is also matched because `vue-loader` are applied to `.vue` files.

    Similarly, if you have configured `style-loader` + `css-loader` + `sass-loader` for `*.scss` files:

    ``` html
    <style scoped lang="scss">
    ```

    Will be returned by `vue-loader` as:

    ``` js
    import 'source.vue?vue&type=style&index=1&scoped&lang=scss'
    ```

    And webpack will expand it to:

    ``` js
    import 'style-loader!css-loader!sass-loader!vue-loader!source.vue?vue&type=style&index=1&scoped&lang=scss'
    ```

3. When processing the expanded requests, the main `vue-loader` will get invoked again. This time though, the loader notices that the request has queries and is targeting a specific block only. So it selects (`src/select.ts`) the inner content of the target block and passes it on to the loaders matched after it.

4. For the `<script>` block, this is pretty much it. For `<template>` and `<style>` blocks though, a few extra tasks need to be performed:

    - We need to compile the template using the Vue template compiler;
    - We need to post-process the CSS in `<style scoped>` blocks, **before** `css-loader`.

    Technically, these are additional loaders (`src/templateLoader.ts` and `src/stylePostLoader.ts`) that need to be injected into the expanded loader chain. It would be very complicated if the end users have to configure this themselves, so `VueLoaderPlugin` also injects a global [Pitching Loader](https://webpack.js.org/api/loaders/#pitching-loader) (`src/pitcher.ts`) that intercepts Vue `<template>` and `<style>` requests and injects the necessary loaders. The final requests look like the following:

    ``` js
    // <template lang="pug">
    import 'vue-loader/template-loader!pug-loader!vue-loader!source.vue?vue&type=template'

    // <style scoped lang="scss">
    import 'style-loader!css-loader!vue-loader/style-post-loader!sass-loader!vue-loader!source.vue?vue&type=style&index=1&scoped&lang=scss'
    ```


code:
const qs = require('querystring')
const { attrsToQuery, genMatchResource } = require('./utils')

module.exports = function genCustomBlocksCode(
  loaderContext,
  blocks,
  resourcePath,
  resourceQuery,
  stringifyRequest,
  enableInlineMatchResource
) {
  return (
    `\n/* custom blocks */\n` +
    blocks
      .map((block, i) => {
        const src = block.attrs.src || resourcePath
        const attrsQuery = attrsToQuery(block.attrs)
        const issuerQuery = block.attrs.src
          ? `&issuerPath=${qs.escape(resourcePath)}`
          : ''
        const inheritQuery = resourceQuery ? `&${resourceQuery.slice(1)}` : ''
        const externalQuery = block.attrs.src ? `&external` : ``
        const query = `?vue&type=custom&index=${i}&blockType=${qs.escape(
          block.type
        )}${issuerQuery}${attrsQuery}${inheritQuery}${externalQuery}`

        let customRequest

        if (enableInlineMatchResource) {
          customRequest = stringifyRequest(
            genMatchResource(loaderContext, src, query, block.attrs.lang)
          )
        } else {
          customRequest = stringifyRequest(src + query)
        }
        return (
          `import block${i} from ${customRequest}\n` +
          `if (typeof block${i} === 'function') block${i}(component)`
        )
      })
      .join(`\n`) +
    `\n`
  )
}


code:
const hotReloadAPIPath = JSON.stringify(require.resolve('vue-hot-reload-api'))

const genTemplateHotReloadCode = (id, request) => {
  return `
    module.hot.accept(${request}, function () {
      api.rerender('${id}', {
        render: render,
        staticRenderFns: staticRenderFns
      })
    })
  `.trim()
}

exports.genHotReloadCode = (id, functional, templateRequest) => {
  return `
/* hot reload */
if (module.hot) {
  var api = require(${hotReloadAPIPath})
  api.install(require('vue'))
  if (api.compatible) {
    module.hot.accept()
    if (!api.isRecorded('${id}')) {
      api.createRecord('${id}', component.options)
    } else {
      api.${functional ? 'rerender' : 'reload'}('${id}', component.options)
    }
    ${templateRequest ? genTemplateHotReloadCode(id, templateRequest) : ''}
  }
}
  `.trim()
}


code:
const { attrsToQuery, genMatchResource } = require('./utils')
const hotReloadAPIPath = JSON.stringify(require.resolve('vue-hot-reload-api'))
const nonWhitespaceRE = /\S+/

module.exports = function genStyleInjectionCode(
  loaderContext,
  styles,
  id,
  resourcePath,
  stringifyRequest,
  needsHotReload,
  needsExplicitInjection,
  isProduction,
  enableInlineMatchResource
) {
  let styleImportsCode = ``
  let styleInjectionCode = ``
  let cssModulesHotReloadCode = ``

  let hasCSSModules = false
  const cssModuleNames = new Map()

  function genStyleRequest(style, i) {
    const src = style.src || resourcePath
    const attrsQuery = attrsToQuery(style.attrs, 'css')
    const lang = String(style.attrs.lang || 'css')
    const inheritQuery = loaderContext.resourceQuery.slice(1)
      ? `&${loaderContext.resourceQuery.slice(1)}`
      : ''
    // make sure to only pass id not src importing so that we don't inject
    // duplicate tags when multiple components import the same css file
    const idQuery = !style.src || style.scoped ? `&id=${id}` : ``
    const prodQuery = isProduction ? `&prod` : ``
    const externalQuery = style.src ? `&external` : ``
    const query = `?vue&type=style&index=${i}${idQuery}${prodQuery}${attrsQuery}${inheritQuery}${externalQuery}`
    let styleRequest
    if (enableInlineMatchResource) {
      styleRequest = stringifyRequest(genMatchResource(loaderContext, src, query, lang))
    } else {
      styleRequest = stringifyRequest(src + query)
    }
    return styleRequest
  }

  function genCSSModulesCode(style, request, i) {
    hasCSSModules = true

    const moduleName = style.module === true ? '$style' : style.module
    if (cssModuleNames.has(moduleName)) {
      loaderContext.emitError(`CSS module name ${moduleName} is not unique!`)
    }
    cssModuleNames.set(moduleName, true)

    // `(vue-)style-loader` exports the name-to-hash map directly
    // `css-loader` exports it in `.locals`
    const locals = `(style${i}.locals || style${i})`
    const name = JSON.stringify(moduleName)

    if (!needsHotReload) {
      styleInjectionCode += `this[${name}] = ${locals}\n`
    } else {
      styleInjectionCode += `
        cssModules[${name}] = ${locals}
        Object.defineProperty(this, ${name}, {
          configurable: true,
          get: function () {
            return cssModules[${name}]
          }
        })
      `
      cssModulesHotReloadCode += `
        module.hot && module.hot.accept([${request}], function () {
          var oldLocals = cssModules[${name}]
          if (oldLocals) {
            var newLocals = require(${request})
            if (JSON.stringify(newLocals) !== JSON.stringify(oldLocals)) {
              cssModules[${name}] = newLocals
              require(${hotReloadAPIPath}).rerender("${id}")
            }
          }
        })
      `
    }
  }

  // empty styles: with no `src` specified or only contains whitespaces
  const isNotEmptyStyle = (style) =>
    style.src || nonWhitespaceRE.test(style.content)
  // explicit injection is needed in SSR (for critical CSS collection)
  // or in Shadow Mode (for injection into shadow root)
  // In these modes, vue-style-loader exports objects with the __inject__
  // method; otherwise we simply import the styles.
  if (!needsExplicitInjection) {
    styles.forEach((style, i) => {
      // do not generate requests for empty styles
      if (isNotEmptyStyle(style)) {
        const request = genStyleRequest(style, i)
        styleImportsCode += `import style${i} from ${request}\n`
        if (style.module) genCSSModulesCode(style, request, i)
      }
    })
  } else {
    styles.forEach((style, i) => {
      if (isNotEmptyStyle(style)) {
        const request = genStyleRequest(style, i)
        styleInjectionCode +=
          `var style${i} = require(${request})\n` +
          `if (style${i}.__inject__) style${i}.__inject__(context)\n`
        if (style.module) genCSSModulesCode(style, request, i)
      }
    })
  }

  if (!needsExplicitInjection && !hasCSSModules) {
    return styleImportsCode
  }

  return `
${styleImportsCode}
${hasCSSModules && needsHotReload ? `var cssModules = {}` : ``}
${needsHotReload ? `var disposed = false` : ``}

function injectStyles (context) {
  ${needsHotReload ? `if (disposed) return` : ``}
  ${styleInjectionCode}
}

${
  needsHotReload
    ? `
  module.hot && module.hot.dispose(function (data) {
    disposed = true
  })
`
    : ``
}

${cssModulesHotReloadCode}
  `.trim()
}


code:
const qs = require('querystring')

// these are built-in query parameters so should be ignored
// if the user happen to add them as attrs
const ignoreList = ['id', 'index', 'src', 'type']

// transform the attrs on a SFC block descriptor into a resourceQuery string
exports.attrsToQuery = (attrs, langFallback) => {
  let query = ``
  for (const name in attrs) {
    const value = attrs[name]
    if (!ignoreList.includes(name)) {
      query += `&${qs.escape(name)}=${value ? qs.escape(value) : ``}`
    }
  }
  if (langFallback && !(`lang` in attrs)) {
    query += `&lang=${langFallback}`
  }
  return query
}

exports.genMatchResource = (context, resourcePath, resourceQuery, lang) => {
  resourceQuery = resourceQuery || ''

  const loaders = []
  const parsedQuery = qs.parse(resourceQuery.slice(1))

  // process non-external resources
  if ('vue' in parsedQuery && !('external' in parsedQuery)) {
    const currentRequest = context.loaders
      .slice(context.loaderIndex)
      .map((obj) => obj.request)
    loaders.push(...currentRequest)
  }
  const loaderString = loaders.join('!')

  return `${resourcePath}${lang ? `.${lang}` : ''}${resourceQuery}!=!${
    loaderString ? `${loaderString}!` : ''
  }${resourcePath}${resourceQuery}`
}

exports.testWebpack5 = (compiler) => {
  if (!compiler) {
    return false
  }
  const webpackVersion = compiler.webpack && compiler.webpack.version
  return Boolean(webpackVersion && Number(webpackVersion.split('.')[0]) > 4)
}


code:
// resolve compilers to use.

let cached

exports.resolveCompiler = function (ctx, loaderContext) {
  if (cached) {
    return cached
  }

  // check 2.7
  try {
    const pkg = loadFromContext('vue/package.json', ctx)
    const [major, minor] = pkg.version.split('.')
    if (major === '2' && Number(minor) >= 7) {
      return (cached = {
        is27: true,
        compiler: loadFromContext('vue/compiler-sfc', ctx),
        templateCompiler: undefined
      })
    }
  } catch (e) {}

  return (cached = {
    compiler: require('@vue/component-compiler-utils'),
    templateCompiler: loadTemplateCompiler(ctx, loaderContext)
  })
}

function loadFromContext(path, ctx) {
  return require(require.resolve(path, {
    paths: [ctx]
  }))
}

function loadTemplateCompiler(ctx, loaderContext) {
  try {
    return loadFromContext('vue-template-compiler', ctx)
  } catch (e) {
    if (loaderContext) {
      if (/version mismatch/.test(e.toString())) {
        loaderContext.emitError(e)
      } else {
        loaderContext.emitError(
          new Error(
            `[vue-loader] vue-template-compiler must be installed as a peer dependency, ` +
              `or a compatible compiler implementation must be passed via options.`
          )
        )
      }
    } else {
      throw e
    }
  }
}


code:
const fs = require('fs')
const path = require('path')
const { resolveCompiler } = require('./compiler')

const cache = new Map()

exports.setDescriptor = function setDescriptor(filename, entry) {
  cache.set(cleanQuery(filename), entry)
}

exports.getDescriptor = function getDescriptor(
  filename,
  options,
  loaderContext
) {
  filename = cleanQuery(filename)
  if (cache.has(filename)) {
    return cache.get(filename)
  }

  // This function should only be called after the descriptor has been
  // cached by the main loader.
  // If this is somehow called without a cache hit, it's probably due to sub
  // loaders being run in separate threads. The only way to deal with this is to
  // read from disk directly...
  const source = fs.readFileSync(filename, 'utf-8')
  const sourceRoot = path.dirname(
    path.relative(loaderContext.rootContext, loaderContext.resourcePath)
  )
  const { compiler, templateCompiler } = resolveCompiler(
    loaderContext.rootContext
  )
  const descriptor = compiler.parse({
    source,
    compiler: options.compiler || templateCompiler,
    filename,
    sourceRoot,
    needMap: loaderContext.sourceMap
  })
  cache.set(filename, descriptor)
  return descriptor
}

function cleanQuery(str) {
  const i = str.indexOf('?')
  return i > 0 ? str.slice(0, i) : str
}


code:
import { Plugin } from 'webpack'
import { VueTemplateCompiler } from '@vue/component-compiler-utils/dist/types'
import { CompilerOptions } from 'vue-template-compiler'

declare namespace VueLoader {
  class VueLoaderPlugin extends Plugin {}

  interface VueLoaderOptions {
    transformAssetUrls?: { [tag: string]: string | Array<string> }
    compiler?: VueTemplateCompiler
    compilerOptions?: CompilerOptions
    transpileOptions?: Object
    optimizeSSR?: boolean
    hotReload?: boolean
    productionMode?: boolean
    shadowMode?: boolean
    cacheDirectory?: string
    cacheIdentifier?: string
    prettify?: boolean
    exposeFilename?: boolean
    experimentalInlineMatchResource?: boolean
  }
}

export = VueLoader


code:
const path = require('path')
const hash = require('hash-sum')
const qs = require('querystring')
const plugin = require('./plugin')
const selectBlock = require('./select')
const loaderUtils = require('loader-utils')
const {
  attrsToQuery,
  testWebpack5,
  genMatchResource
} = require('./codegen/utils')
const genStylesCode = require('./codegen/styleInjection')
const { genHotReloadCode } = require('./codegen/hotReload')
const genCustomBlocksCode = require('./codegen/customBlocks')
const componentNormalizerPath = require.resolve('./runtime/componentNormalizer')
const { NS } = require('./plugin')
const { resolveCompiler } = require('./compiler')
const { setDescriptor } = require('./descriptorCache')

let errorEmitted = false

module.exports = function (source) {
  const loaderContext = this

  if (!errorEmitted && !loaderContext['thread-loader'] && !loaderContext[NS]) {
    loaderContext.emitError(
      new Error(
        `vue-loader was used without the corresponding plugin. ` +
          `Make sure to include VueLoaderPlugin in your webpack config.`
      )
    )
    errorEmitted = true
  }

  const stringifyRequest = (r) => loaderUtils.stringifyRequest(loaderContext, r)

  const {
    mode,
    target,
    request,
    minimize,
    sourceMap,
    rootContext,
    resourcePath,
    resourceQuery: _resourceQuery = '',
    _compiler
  } = loaderContext
  const isWebpack5 = testWebpack5(_compiler)
  const rawQuery = _resourceQuery.slice(1)
  const resourceQuery = rawQuery ? `&${rawQuery}` : ''
  const incomingQuery = qs.parse(rawQuery)
  const options = loaderUtils.getOptions(loaderContext) || {}
  const enableInlineMatchResource =
    isWebpack5 && Boolean(options.experimentalInlineMatchResource)
  const isServer = target === 'node'
  const isShadow = !!options.shadowMode
  const isProduction =
    mode === 'production' ||
    options.productionMode ||
    minimize ||
    process.env.NODE_ENV === 'production'

  const filename = path.basename(resourcePath)
  const context = rootContext || process.cwd()
  const sourceRoot = path.dirname(path.relative(context, resourcePath))

  const { compiler, templateCompiler } = resolveCompiler(context, loaderContext)

  const descriptor = compiler.parse({
    source,
    compiler: options.compiler || templateCompiler,
    filename,
    sourceRoot,
    needMap: sourceMap
  })

  // cache descriptor
  setDescriptor(resourcePath, descriptor)

  // module id for scoped CSS & hot-reload
  const rawShortFilePath = path
    .relative(context, resourcePath)
    .replace(/^(\.\.[\/\\])+/, '')
  const shortFilePath = rawShortFilePath.replace(/\\/g, '/')
  const id = hash(
    isProduction
      ? shortFilePath + '\n' + source.replace(/\r\n/g, '\n')
      : shortFilePath
  )

  // if the query has a type field, this is a language block request
  // e.g. foo.vue?type=template&id=xxxxx
  // and we will return early
  if (incomingQuery.type) {
    return selectBlock(
      descriptor,
      id,
      options,
      loaderContext,
      incomingQuery,
      !!options.appendExtension
    )
  }

  // feature information
  const hasScoped = descriptor.styles.some((s) => s.scoped)
  const hasFunctional =
    descriptor.template && descriptor.template.attrs.functional
  const needsHotReload =
    !isServer &&
    !isProduction &&
    (descriptor.script || descriptor.scriptSetup || descriptor.template) &&
    options.hotReload !== false

  // script
  let scriptImport = `var script = {}`
  // let isTS = false
  const { script, scriptSetup } = descriptor
  if (script || scriptSetup) {
    const lang = (script && script.lang) || (scriptSetup && scriptSetup.lang)
    // isTS = !!(lang && /tsx?/.test(lang))
    const externalQuery =
      script && !scriptSetup && script.src ? `&external` : ``
    const src = (script && !scriptSetup && script.src) || resourcePath
    const attrsQuery = attrsToQuery((scriptSetup || script).attrs, 'js')
    const query = `?vue&type=script${attrsQuery}${resourceQuery}${externalQuery}`

    let scriptRequest
    if (enableInlineMatchResource) {
      scriptRequest = stringifyRequest(
        genMatchResource(loaderContext, src, query, lang || 'js')
      )
    } else {
      scriptRequest = stringifyRequest(src + query)
    }
    scriptImport =
      `import script from ${scriptRequest}\n` + `export * from ${scriptRequest}` // support named exports
  }

  // template
  let templateImport = `var render, staticRenderFns`
  let templateRequest
  if (descriptor.template) {
    const src = descriptor.template.src || resourcePath
    const externalQuery = descriptor.template.src ? `&external` : ``
    const idQuery = `&id=${id}`
    const scopedQuery = hasScoped ? `&scoped=true` : ``
    const attrsQuery = attrsToQuery(descriptor.template.attrs)
    // const tsQuery =
    // options.enableTsInTemplate !== false && isTS ? `&ts=true` : ``
    const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}${resourceQuery}${externalQuery}`
    if (enableInlineMatchResource) {
      templateRequest = stringifyRequest(
        // TypeScript syntax in template expressions is not supported in Vue 2, so the lang is always 'js'
        genMatchResource(loaderContext, src, query, 'js')
      )
    } else {
      templateRequest = stringifyRequest(src + query)
    }
    templateImport = `import { render, staticRenderFns } from ${templateRequest}`
  }

  // styles
  let stylesCode = ``
  if (descriptor.styles.length) {
    stylesCode = genStylesCode(
      loaderContext,
      descriptor.styles,
      id,
      resourcePath,
      stringifyRequest,
      needsHotReload,
      isServer || isShadow, // needs explicit injection?
      isProduction,
      enableInlineMatchResource
    )
  }

  let code =
    `
${templateImport}
${scriptImport}
${stylesCode}

/* normalize component */
import normalizer from ${stringifyRequest(`!${componentNormalizerPath}`)}
var component = normalizer(
  script,
  render,
  staticRenderFns,
  ${hasFunctional ? `true` : `false`},
  ${/injectStyles/.test(stylesCode) ? `injectStyles` : `null`},
  ${hasScoped ? JSON.stringify(id) : `null`},
  ${isServer ? JSON.stringify(hash(request)) : `null`}
  ${isShadow ? `,true` : ``}
)
  `.trim() + `\n`

  if (descriptor.customBlocks && descriptor.customBlocks.length) {
    code += genCustomBlocksCode(
      loaderContext,
      descriptor.customBlocks,
      resourcePath,
      resourceQuery,
      stringifyRequest,
      enableInlineMatchResource
    )
  }

  if (needsHotReload) {
    code += `\n` + genHotReloadCode(id, hasFunctional, templateRequest)
  }

  // Expose filename. This is used by the devtools and Vue runtime warnings.
  if (!isProduction) {
    // Expose the file's full path in development, so that it can be opened
    // from the devtools.
    code += `\ncomponent.options.__file = ${JSON.stringify(
      rawShortFilePath.replace(/\\/g, '/')
    )}`
  } else if (options.exposeFilename) {
    // Libraries can opt-in to expose their components' filenames in production builds.
    // For security reasons, only expose the file's basename in production.
    code += `\ncomponent.options.__file = ${JSON.stringify(filename)}`
  }

  code += `\nexport default component.exports`
  return code
}

module.exports.VueLoaderPlugin = plugin