code:
const qs = require('querystring')
const loaderUtils = require('loader-utils')
const hash = require('hash-sum')
const selfPath = require.resolve('../index')
const templateLoaderPath = require.resolve('./templateLoader')
const stylePostLoaderPath = require.resolve('./stylePostLoader')
const { resolveCompiler } = require('../compiler')
const { testWebpack5 } = require('../codegen/utils')

const isESLintLoader = (l) => /(\/|\\|@)eslint-loader/.test(l.path)
const isNullLoader = (l) => /(\/|\\|@)null-loader/.test(l.path)
const isCSSLoader = (l) => /(\/|\\|@)css-loader/.test(l.path)
const isCacheLoader = (l) => /(\/|\\|@)cache-loader/.test(l.path)
const isPitcher = (l) => l.path !== __filename
const isPreLoader = (l) => !l.pitchExecuted
const isPostLoader = (l) => l.pitchExecuted

const dedupeESLintLoader = (loaders) => {
  const res = []
  let seen = false
  loaders.forEach((l) => {
    if (!isESLintLoader(l)) {
      res.push(l)
    } else if (!seen) {
      seen = true
      res.push(l)
    }
  })
  return res
}

const shouldIgnoreCustomBlock = (loaders) => {
  const actualLoaders = loaders.filter((loader) => {
    // vue-loader
    if (loader.path === selfPath) {
      return false
    }

    // cache-loader
    if (isCacheLoader(loader)) {
      return false
    }

    return true
  })
  return actualLoaders.length === 0
}

module.exports = (code) => code

// This pitching loader is responsible for intercepting all vue block requests
// and transform it into appropriate requests.
module.exports.pitch = function (remainingRequest) {
  const options = loaderUtils.getOptions(this)
  const { cacheDirectory, cacheIdentifier } = options
  const query = qs.parse(this.resourceQuery.slice(1))
  const isWebpack5 = testWebpack5(this._compiler)

  let loaders = this.loaders

  // if this is a language block request, eslint-loader may get matched
  // multiple times
  if (query.type) {
    // if this is an inline block, since the whole file itself is being linted,
    // remove eslint-loader to avoid duplicate linting.
    if (/\.vue$/.test(this.resourcePath)) {
      loaders = loaders.filter((l) => !isESLintLoader(l))
    } else {
      // This is a src import. Just make sure there's not more than 1 instance
      // of eslint present.
      loaders = dedupeESLintLoader(loaders)
    }
  }

  // remove self
  loaders = loaders.filter(isPitcher)

  // do not inject if user uses null-loader to void the type (#1239)
  if (loaders.some(isNullLoader)) {
    return
  }

  const genRequest = (loaders, lang) => {
    // Important: dedupe since both the original rule
    // and the cloned rule would match a source import request.
    // also make sure to dedupe based on loader path.
    // assumes you'd probably never want to apply the same loader on the same
    // file twice.
    // Exception: in Vue CLI we do need two instances of postcss-loader
    // for user config and inline minification. So we need to dedupe baesd on
    // path AND query to be safe.
    const seen = new Map()
    const loaderStrings = []
    const enableInlineMatchResource =
      isWebpack5 && options.experimentalInlineMatchResource

    loaders.forEach((loader) => {
      const identifier =
        typeof loader === 'string' ? loader : loader.path + loader.query
      const request = typeof loader === 'string' ? loader : loader.request
      if (!seen.has(identifier)) {
        seen.set(identifier, true)
        // loader.request contains both the resolved loader path and its options
        // query (e.g. ??ref-0)
        loaderStrings.push(request)
      }
    })
    if (enableInlineMatchResource) {
      return loaderUtils.stringifyRequest(
        this,
        `${this.resourcePath}${lang ? `.${lang}` : ''}${
          this.resourceQuery
        }!=!-!${[...loaderStrings, this.resourcePath + this.resourceQuery].join('!')}`
      )
    }

    return loaderUtils.stringifyRequest(
      this,
      '-!' +
        [...loaderStrings, this.resourcePath + this.resourceQuery].join('!')
    )
  }

  // Inject style-post-loader before css-loader for scoped CSS and trimming
  if (query.type === `style`) {
    if (isWebpack5 && this._compiler.options.experiments && this._compiler.options.experiments.css) {
      // If user enables `experiments.css`, then we are trying to emit css code directly.
      // Although we can target requests like `xxx.vue?type=style` to match `type: "css"`,
      // it will make the plugin a mess.
      if (!options.experimentalInlineMatchResource) {
        this.emitError(
          new Error(
            '`experimentalInlineMatchResource` should be enabled if `experiments.css` enabled currently'
          )
        )
        return ''
      }

      if (query.inline || query.module) {
        this.emitError(
          new Error(
            '`inline` or `module` is currently not supported with `experiments.css` enabled'
          )
        )
        return ''
      }

      const loaderString = [stylePostLoaderPath, ...loaders]
        .map((loader) => {
          return typeof loader === 'string' ? loader : loader.request
        })
        .join('!')

        const styleRequest = loaderUtils.stringifyRequest(
          this,
          `${this.resourcePath}${query.lang ? `.${query.lang}` : ''}${
            this.resourceQuery
          }!=!-!${loaderString}!${this.resourcePath + this.resourceQuery}`
        )
        return `@import ${styleRequest};`
    }

    const cssLoaderIndex = loaders.findIndex(isCSSLoader)
    if (cssLoaderIndex > -1) {
      const afterLoaders = loaders.slice(0, cssLoaderIndex + 1)
      const beforeLoaders = loaders.slice(cssLoaderIndex + 1)
      const request = genRequest(
        [...afterLoaders, stylePostLoaderPath, ...beforeLoaders],
        query.lang || 'css'
      )
      // console.log(request)
      return query.module
        ? `export { default } from  ${request}; export * from ${request}`
        : `export * from ${request}`
    }
  }

  // for templates: inject the template compiler & optional cache
  if (query.type === `template`) {
    const path = require('path')
    const cacheLoader =
      cacheDirectory && cacheIdentifier
        ? [
            `${require.resolve('cache-loader')}?${JSON.stringify({
              // For some reason, webpack fails to generate consistent hash if we
              // use absolute paths here, even though the path is only used in a
              // comment. For now we have to ensure cacheDirectory is a relative path.
              cacheDirectory: (path.isAbsolute(cacheDirectory)
                ? path.relative(process.cwd(), cacheDirectory)
                : cacheDirectory
              ).replace(/\\/g, '/'),
              cacheIdentifier: hash(cacheIdentifier) + '-vue-loader-template'
            })}`
          ]
        : []

    const preLoaders = loaders.filter(isPreLoader)
    const postLoaders = loaders.filter(isPostLoader)
    const { is27 } = resolveCompiler(this.rootContext, this)

    const request = genRequest([
      ...cacheLoader,
      ...postLoaders,
      ...(is27 ? [] : [templateLoaderPath + `??vue-loader-options`]),
      ...preLoaders
    ])

    // the template compiler uses esm exports
    return `export * from ${request}`
  }

  // if a custom block has no other matching loader other than vue-loader itself
  // or cache-loader, we should ignore it
  if (query.type === `custom` && shouldIgnoreCustomBlock(loaders)) {
    return ``
  }

  // When the user defines a rule that has only resourceQuery but no test,
  // both that rule and the cloned rule will match, resulting in duplicated
  // loaders. Therefore it is necessary to perform a dedupe here.
  const request = genRequest(loaders)
  return `import mod from ${request}; export default mod; export * from ${request}`
}


code:
const qs = require('querystring')
const { resolveCompiler } = require('../compiler')

// This is a post loader that handles scoped CSS transforms.
// Injected right before css-loader by the global pitcher (../pitch.js)
// for any <style scoped> selection requests initiated from within vue files.
module.exports = function (source, inMap) {
  const query = qs.parse(this.resourceQuery.slice(1))
  const { compiler } = resolveCompiler(this.rootContext, this)
  const { code, map, errors } = compiler.compileStyle({
    source,
    filename: this.resourcePath,
    id: `data-v-${query.id}`,
    map: inMap,
    scoped: !!query.scoped,
    isProd: query.prod != null,
    trim: true
  })

  if (errors.length) {
    this.callback(errors[0])
  } else {
    this.callback(null, code, map)
  }
}

license: mit


code:
const qs = require('querystring')
const loaderUtils = require('loader-utils')
const { resolveCompiler } = require('../compiler')
const { getDescriptor } = require('../descriptorCache')
const { resolveScript } = require('../resolveScript')

// Loader that compiles raw template into JavaScript functions.
// This is injected by the global pitcher (../pitch) for template
// selection requests initiated from vue files.
module.exports = function (source) {
  const loaderContext = this
  const filename = this.resourcePath
  const ctx = this.rootContext
  const query = qs.parse(this.resourceQuery.slice(1))

  // although this is not the main vue-loader, we can get access to the same
  // vue-loader options because we've set an ident in the plugin and used that
  // ident to create the request for this loader in the pitcher.
  const options = loaderUtils.getOptions(loaderContext) || {}
  const { id } = query
  const isServer = loaderContext.target === 'node'
  const isProduction =
    options.productionMode ||
    loaderContext.minimize ||
    process.env.NODE_ENV === 'production'
  const isFunctional = query.functional

  const compilerOptions = Object.assign(
    {
      outputSourceRange: true
    },
    options.compilerOptions,
    {
      scopeId: query.scoped ? `data-v-${id}` : null,
      comments: query.comments
    }
  )

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

  const descriptor = getDescriptor(filename, options, loaderContext)
  const script = resolveScript(descriptor, id, options, loaderContext)

  // Prettier 3 APIs are all async
  // but `vue/compiler-sfc` and `@vue/component-compiler-utils` can only use sync function to format code
  let hasCompatiblePrettier = false
  try {
    const prettier = require('prettier/package.json')
    const major = parseInt(prettier.version.split('.')[0], 10)
    if (major === 1 || major === 2) {
      hasCompatiblePrettier = true
    }
  } catch (e) {}

  // for vue/compiler-sfc OR @vue/component-compiler-utils
  const finalOptions = {
    source,
    filename: this.resourcePath,
    compiler: options.compiler || templateCompiler,
    compilerOptions,
    // allow customizing behavior of vue-template-es2015-compiler
    transpileOptions: options.transpileOptions,
    transformAssetUrls: options.transformAssetUrls || true,
    isProduction,
    isFunctional,
    optimizeSSR: isServer && options.optimizeSSR !== false,
    prettify: options.prettify === undefined ? hasCompatiblePrettier : options.prettify,
    bindings: script ? script.bindings : undefined
  }

  const compiled = compiler.compileTemplate(finalOptions)

  // tips
  if (compiled.tips && compiled.tips.length) {
    compiled.tips.forEach((tip) => {
      loaderContext.emitWarning(typeof tip === 'object' ? tip.msg : tip)
    })
  }

  // errors
  if (compiled.errors && compiled.errors.length) {
    const generateCodeFrame =
      (templateCompiler && templateCompiler.generateCodeFrame) ||
      compiler.generateCodeFrame
    // 2.6 compiler outputs errors as objects with range
    if (generateCodeFrame && finalOptions.compilerOptions.outputSourceRange) {
      // TODO account for line offset in case template isn't placed at top
      // of the file
      loaderContext.emitError(
        `\n\n  Errors compiling template:\n\n` +
          compiled.errors
            .map(({ msg, start, end }) => {
              const frame = generateCodeFrame(source, start, end)
              return `  ${msg}\n\n${pad(frame)}`
            })
            .join(`\n\n`) +
          '\n'
      )
    } else {
      loaderContext.emitError(
        `\n  Error compiling template:\n${pad(compiled.source)}\n` +
          compiled.errors.map((e) => `  - ${e}`).join('\n') +
          '\n'
      )
    }
  }

  const { code } = compiled

  // finish with ESM exports
  return code + `\nexport { render, staticRenderFns }`
}

function pad(source) {
  return source
    .split(/\r?\n/)
    .map((line) => `  ${line}`)
    .join('\n')
}


code:
const qs = require('querystring')
const RuleSet = require('webpack/lib/RuleSet')
const { resolveCompiler } = require('./compiler')

const id = 'vue-loader-plugin'
const NS = 'vue-loader'

class VueLoaderPlugin {
  apply(compiler) {
    // add NS marker so that the loader can detect and report missing plugin
    if (compiler.hooks) {
      // webpack 4
      compiler.hooks.compilation.tap(id, (compilation) => {
        const normalModuleLoader = compilation.hooks.normalModuleLoader
        normalModuleLoader.tap(id, (loaderContext) => {
          loaderContext[NS] = true
        })
      })
    } else {
      // webpack < 4
      compiler.plugin('compilation', (compilation) => {
        compilation.plugin('normal-module-loader', (loaderContext) => {
          loaderContext[NS] = true
        })
      })
    }

    // use webpack's RuleSet utility to normalize user rules
    const rawRules = compiler.options.module.rules
    const { rules } = new RuleSet(rawRules)

    // find the rule that applies to vue files
    let vueRuleIndex = rawRules.findIndex(createMatcher(`foo.vue`))
    if (vueRuleIndex < 0) {
      vueRuleIndex = rawRules.findIndex(createMatcher(`foo.vue.html`))
    }
    const vueRule = rules[vueRuleIndex]

    if (!vueRule) {
      throw new Error(
        `[VueLoaderPlugin Error] No matching rule for .vue files found.\n` +
          `Make sure there is at least one root-level rule that matches .vue or .vue.html files.`
      )
    }

    if (vueRule.oneOf) {
      throw new Error(
        `[VueLoaderPlugin Error] vue-loader 15 currently does not support vue rules with oneOf.`
      )
    }

    // get the normalized "use" for vue files
    const vueUse = vueRule.use
    // get vue-loader options
    const vueLoaderUseIndex = vueUse.findIndex((u) => {
      return /^vue-loader|(\/|\\|@)vue-loader/.test(u.loader)
    })

    if (vueLoaderUseIndex < 0) {
      throw new Error(
        `[VueLoaderPlugin Error] No matching use for vue-loader is found.\n` +
          `Make sure the rule matching .vue files include vue-loader in its use.`
      )
    }

    // make sure vue-loader options has a known ident so that we can share
    // options by reference in the template-loader by using a ref query like
    // template-loader??vue-loader-options
    const vueLoaderUse = vueUse[vueLoaderUseIndex]
    vueLoaderUse.ident = 'vue-loader-options'
    vueLoaderUse.options = vueLoaderUse.options || {}

    // for each user rule (except the vue rule), create a cloned rule
    // that targets the corresponding language blocks in *.vue files.
    const clonedRules = rules.filter((r) => r !== vueRule).map(cloneRule)

    // rule for template compiler
    const templateCompilerRule = {
      loader: require.resolve('./loaders/templateLoader'),
      resourceQuery: (query) => {
        const parsed = qs.parse(query.slice(1))
        return parsed.vue != null && parsed.type === 'template'
      },
      options: vueLoaderUse.options
    }

    // for each rule that matches plain .js/.ts files, also create a clone and
    // match it against the compiled template code inside *.vue files, so that
    // compiled vue render functions receive the same treatment as user code
    // (mostly babel)
    const { is27 } = resolveCompiler(compiler.options.context)
    let jsRulesForRenderFn = []
    if (is27) {
      const matchesJS = createMatcher(`test.js`)
      // const matchesTS = createMatcher(`test.ts`)
      jsRulesForRenderFn = rules
        .filter((r) => r !== vueRule && matchesJS(r))
        .map(cloneRuleForRenderFn)
    }

    // global pitcher (responsible for injecting template compiler loader & CSS
    // post loader)
    const pitcher = {
      loader: require.resolve('./loaders/pitcher'),
      resourceQuery: (query) => {
        const parsed = qs.parse(query.slice(1))
        return parsed.vue != null
      },
      options: {
        cacheDirectory: vueLoaderUse.options.cacheDirectory,
        cacheIdentifier: vueLoaderUse.options.cacheIdentifier
      }
    }

    // replace original rules
    compiler.options.module.rules = [
      pitcher,
      ...jsRulesForRenderFn,
      ...(is27 ? [templateCompilerRule] : []),
      ...clonedRules,
      ...rules
    ]
  }
}

function createMatcher(fakeFile) {
  return (rule, i) => {
    // #1201 we need to skip the `include` check when locating the vue rule
    const clone = Object.assign({}, rule)
    delete clone.include
    const normalized = RuleSet.normalizeRule(clone, {}, '')
    return !rule.enforce && normalized.resource && normalized.resource(fakeFile)
  }
}

function cloneRule(rule) {
  const { resource, resourceQuery } = rule
  // Assuming `test` and `resourceQuery` tests are executed in series and
  // synchronously (which is true based on RuleSet's implementation), we can
  // save the current resource being matched from `test` so that we can access
  // it in `resourceQuery`. This ensures when we use the normalized rule's
  // resource check, include/exclude are matched correctly.
  let currentResource
  const res = Object.assign({}, rule, {
    resource: {
      test: (resource) => {
        currentResource = resource
        return true
      }
    },
    resourceQuery: (query) => {
      const parsed = qs.parse(query.slice(1))
      if (parsed.vue == null) {
        return false
      }
      if (resource && parsed.lang == null) {
        return false
      }
      const fakeResourcePath = `${currentResource}.${parsed.lang}`
      if (resource && !resource(fakeResourcePath)) {
        return false
      }
      if (resourceQuery && !resourceQuery(query)) {
        return false
      }
      return true
    }
  })

  if (rule.rules) {
    res.rules = rule.rules.map(cloneRule)
  }

  if (rule.oneOf) {
    res.oneOf = rule.oneOf.map(cloneRule)
  }

  return res
}

function cloneRuleForRenderFn(rule) {
  const resource = rule.resource
  const resourceQuery = rule.resourceQuery
  let currentResource

  const res = {
    ...rule,
    resource: (resource) => {
      currentResource = resource
      return true
    },
    resourceQuery: (query) => {
      const parsed = qs.parse(query.slice(1))
      if (parsed.vue == null || parsed.type !== 'template') {
        return false
      }
      const fakeResourcePath = `${currentResource}.${parsed.ts ? `ts` : `js`}`
      if (resource && !resource(fakeResourcePath)) {
        return false
      }
      if (resourceQuery && !resourceQuery(query)) {
        return false
      }
      return true
    }
  }

  // Filter out `thread-loader` from the `use` array.
  // Mitigate https://github.com/vuejs/vue/issues/12828
  // Note this won't work if the `use` filed is a function
  if (Array.isArray(res.use)) {
    const isThreadLoader = (loader) => loader === 'thread-loader' || /\/node_modules\/thread-loader\//.test(loader)

    res.use = res.use.filter(useEntry => {
      const loader = typeof useEntry === 'string' ? useEntry : useEntry.loader
      return !isThreadLoader(loader)
    })
  }

  if (rule.rules) {
    res.rules = rule.rules.map(cloneRuleForRenderFn)
  }

  if (rule.oneOf) {
    res.oneOf = rule.oneOf.map(cloneRuleForRenderFn)
  }

  return res
}

VueLoaderPlugin.NS = NS
module.exports = VueLoaderPlugin


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

const qs = require('querystring')
const id = 'vue-loader-plugin'
const NS = 'vue-loader'
const BasicEffectRulePlugin = require('webpack/lib/rules/BasicEffectRulePlugin')
const BasicMatcherRulePlugin = require('webpack/lib/rules/BasicMatcherRulePlugin')
const RuleSetCompiler = require('webpack/lib/rules/RuleSetCompiler')
const UseEffectRulePlugin = require('webpack/lib/rules/UseEffectRulePlugin')

const objectMatcherRulePlugins = []
try {
  const ObjectMatcherRulePlugin = require('webpack/lib/rules/ObjectMatcherRulePlugin')
  objectMatcherRulePlugins.push(
    new ObjectMatcherRulePlugin('assert', 'assertions'),
    new ObjectMatcherRulePlugin('descriptionData')
  )
} catch (e) {
  const DescriptionDataMatcherRulePlugin = require('webpack/lib/rules/DescriptionDataMatcherRulePlugin')
  objectMatcherRulePlugins.push(new DescriptionDataMatcherRulePlugin())
}

const ruleSetCompiler = new RuleSetCompiler([
  new BasicMatcherRulePlugin('test', 'resource'),
  new BasicMatcherRulePlugin('mimetype'),
  new BasicMatcherRulePlugin('dependency'),
  new BasicMatcherRulePlugin('include', 'resource'),
  new BasicMatcherRulePlugin('exclude', 'resource', true),
  new BasicMatcherRulePlugin('conditions'),
  new BasicMatcherRulePlugin('resource'),
  new BasicMatcherRulePlugin('resourceQuery'),
  new BasicMatcherRulePlugin('resourceFragment'),
  new BasicMatcherRulePlugin('realResource'),
  new BasicMatcherRulePlugin('issuer'),
  new BasicMatcherRulePlugin('compiler'),
  ...objectMatcherRulePlugins,
  new BasicEffectRulePlugin('type'),
  new BasicEffectRulePlugin('sideEffects'),
  new BasicEffectRulePlugin('parser'),
  new BasicEffectRulePlugin('resolve'),
  new BasicEffectRulePlugin('generator'),
  new UseEffectRulePlugin()
])

class VueLoaderPlugin {
  apply(compiler) {
    const normalModule = compiler.webpack
      ? compiler.webpack.NormalModule
      : require('webpack/lib/NormalModule')
    // add NS marker so that the loader can detect and report missing plugin
    compiler.hooks.compilation.tap(id, (compilation) => {
      const normalModuleLoader =
        normalModule.getCompilationHooks(compilation).loader
      normalModuleLoader.tap(id, (loaderContext) => {
        loaderContext[NS] = true
      })
    })

    const rules = compiler.options.module.rules
    let rawVueRule
    let vueRules = []

    for (const rawRule of rules) {
      // skip rules with 'enforce'. eg. rule for eslint-loader
      if (rawRule.enforce) {
        continue
      }
      vueRules = match(rawRule, 'foo.vue')
      if (!vueRules.length) {
        vueRules = match(rawRule, 'foo.vue.html')
      }
      if (vueRules.length > 0) {
        if (rawRule.oneOf) {
          throw new Error(
            `[VueLoaderPlugin Error] vue-loader 15 currently does not support vue rules with oneOf.`
          )
        }
        rawVueRule = rawRule
        break
      }
    }
    if (!vueRules.length) {
      throw new Error(
        `[VueLoaderPlugin Error] No matching rule for .vue files found.\n` +
          `Make sure there is at least one root-level rule that matches .vue or .vue.html files.`
      )
    }

    // get the normalized "use" for vue files
    const vueUse = vueRules
      .filter((rule) => rule.type === 'use')
      .map((rule) => rule.value)

    // get vue-loader options
    const vueLoaderUseIndex = vueUse.findIndex((u) => {
      return /^vue-loader|(\/|\\|@)vue-loader/.test(u.loader)
    })

    if (vueLoaderUseIndex < 0) {
      throw new Error(
        `[VueLoaderPlugin Error] No matching use for vue-loader is found.\n` +
          `Make sure the rule matching .vue files include vue-loader in its use.`
      )
    }

    // make sure vue-loader options has a known ident so that we can share
    // options by reference in the template-loader by using a ref query like
    // template-loader??vue-loader-options
    const vueLoaderUse = vueUse[vueLoaderUseIndex]
    vueLoaderUse.ident = 'vue-loader-options'
    vueLoaderUse.options = vueLoaderUse.options || {}
    const enableInlineMatchResource =
      vueLoaderUse.options.experimentalInlineMatchResource

    // for each user rule (expect the vue rule), create a cloned rule
    // that targets the corresponding language blocks in *.vue files.
    const refs = new Map()
    const clonedRules = rules
      .filter((r) => r !== rawVueRule)
      .map((rawRule) =>
        cloneRule(rawRule, refs, langBlockRuleCheck, langBlockRuleResource)
      )

    // fix conflict with config.loader and config.options when using config.use
    delete rawVueRule.loader
    delete rawVueRule.options
    rawVueRule.use = vueUse

    // rule for template compiler
    const templateCompilerRule = {
      loader: require.resolve('./loaders/templateLoader'),
      resourceQuery: (query) => {
        if (!query) {
          return false
        }
        const parsed = qs.parse(query.slice(1))
        return parsed.vue != null && parsed.type === 'template'
      },
      options: vueLoaderUse.options
    }

    // for each rule that matches plain .js files, also create a clone and
    // match it against the compiled template code inside *.vue files, so that
    // compiled vue render functions receive the same treatment as user code
    // (mostly babel)
    const { is27 } = resolveCompiler(compiler.options.context)
    let jsRulesForRenderFn = []
    if (is27) {
      const skipThreadLoader = true
      jsRulesForRenderFn = rules
        .filter(
          (r) =>
            r !== rawVueRule &&
            (match(r, 'test.js').length > 0 || match(r, 'test.ts').length > 0)
        )
        .map((rawRule) => cloneRule(rawRule, refs, jsRuleCheck, jsRuleResource, skipThreadLoader))
    }

    // global pitcher (responsible for injecting template compiler loader & CSS
    // post loader)
    const pitcher = {
      loader: require.resolve('./loaders/pitcher'),
      resourceQuery: (query) => {
        if (!query) {
          return false
        }
        const parsed = qs.parse(query.slice(1))
        return parsed.vue != null
      },
      options: vueLoaderUse.options
    }
    // replace original rules
    if (enableInlineMatchResource) {
      // Match rules using `vue-loader`
      const vueLoaderRules = rules.filter((rule) => {
        const matchOnce = (use) => {
          let loaderString = ''

          if (!use) {
            return loaderString
          }

          if (typeof use === 'string') {
            loaderString = use
          } else if (Array.isArray(use)) {
            loaderString = matchOnce(use[0])
          } else if (typeof use === 'object' && use.loader) {
            loaderString = use.loader
          }
          return loaderString
        }

        const loader = rule.loader || matchOnce(rule.use)
        return (
          loader === require('../package.json').name ||
          loader.startsWith(require.resolve('./index'))
        )
      })

      compiler.options.module.rules = [
        pitcher,
        ...rules.filter((rule) => !vueLoaderRules.includes(rule)),
        ...(is27 ? [templateCompilerRule] : []),
        ...clonedRules,
        ...vueLoaderRules
      ]
    } else {
      compiler.options.module.rules = [
        pitcher,
        ...jsRulesForRenderFn,
        ...(is27 ? [templateCompilerRule] : []),
        ...clonedRules,
        ...rules
      ]
    }
  }
}

const matcherCache = new WeakMap()

function match(rule, fakeFile) {
  let ruleSet = matcherCache.get(rule)
  if (!ruleSet) {
    // skip the `include` check when locating the vue rule
    const clonedRawRule = { ...rule }
    delete clonedRawRule.include

    ruleSet = ruleSetCompiler.compile([clonedRawRule])
    matcherCache.set(rule, ruleSet)
  }

  return ruleSet.exec({
    resource: fakeFile
  })
}

const langBlockRuleCheck = (query, rule) => {
  return (
    query.type === 'custom' || !rule.conditions.length || query.lang != null
  )
}

const langBlockRuleResource = (query, resource) => `${resource}.${query.lang}`

const jsRuleCheck = (query) => {
  return query.type === 'template'
}

const jsRuleResource = (query, resource) =>
  `${resource}.${query.ts ? `ts` : `js`}`

let uid = 0

function cloneRule(rawRule, refs, ruleCheck, ruleResource, skipThreadLoader) {
  const compiledRule = ruleSetCompiler.compileRule(
    `clonedRuleSet-${++uid}`,
    rawRule,
    refs
  )

  // do not process rule with enforce
  if (!rawRule.enforce) {
    const ruleUse = compiledRule.effects
      .filter((effect) => effect.type === 'use')
      .map((effect) => effect.value)
    // fix conflict with config.loader and config.options when using config.use
    delete rawRule.loader
    delete rawRule.options

    // Filter out `thread-loader` from the `use` array.
    // Mitigate https://github.com/vuejs/vue/issues/12828
    // Note this won't work if the `use` filed is a function
    if (skipThreadLoader && Array.isArray(ruleUse)) {
      const isThreadLoader = (loader) => loader === 'thread-loader' || /\/node_modules\/thread-loader\//.test(loader)
      rawRule.use = ruleUse.filter(useEntry => {
        const loader = typeof useEntry === 'string' ? useEntry : useEntry.loader
        return !isThreadLoader(loader)
      })
    } else {
      rawRule.use = ruleUse
    }
  }

  let currentResource
  const res = {
    ...rawRule,
    resource: (resources) => {
      currentResource = resources
      return true
    },
    resourceQuery: (query) => {
      if (!query) {
        return false
      }

      const parsed = qs.parse(query.slice(1))
      if (parsed.vue == null) {
        return false
      }
      if (!ruleCheck(parsed, compiledRule)) {
        return false
      }
      const fakeResourcePath = ruleResource(parsed, currentResource)
      for (const condition of compiledRule.conditions) {
        // add support for resourceQuery
        const request =
          condition.property === 'resourceQuery' ? query : fakeResourcePath
        if (condition && !condition.fn(request)) {
          return false
        }
      }
      return true
    }
  }

  delete res.test

  if (rawRule.rules) {
    res.rules = rawRule.rules.map((rule) =>
      cloneRule(rule, refs, ruleCheck, ruleResource)
    )
  }

  if (rawRule.oneOf) {
    res.oneOf = rawRule.oneOf.map((rule) =>
      cloneRule(rule, refs, ruleCheck, ruleResource)
    )
  }

  return res
}

VueLoaderPlugin.NS = NS
module.exports = VueLoaderPlugin


code:
const { testWebpack5 } = require('./codegen/utils')
const NS = 'vue-loader'
class VueLoaderPlugin {
  apply(compiler) {
    let Ctor = null
    if (testWebpack5(compiler)) {
      // webpack5 and upper
      Ctor = require('./plugin-webpack5')
    } else {
      // webpack4 and lower
      Ctor = require('./plugin-webpack4')
    }
    new Ctor().apply(compiler)
  }
}
VueLoaderPlugin.NS = NS
module.exports = VueLoaderPlugin


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

const clientCache = new WeakMap()
const serverCache = new WeakMap()

exports.resolveScript = function resolveScript(
  descriptor,
  scopeId,
  options,
  loaderContext
) {
  if (!descriptor.script && !descriptor.scriptSetup) {
    return null
  }

  const { compiler } = resolveCompiler(loaderContext.rootContext, loaderContext)
  if (!compiler.compileScript) {
    if (descriptor.scriptSetup) {
      loaderContext.emitError(
        'The version of Vue you are using does not support <script setup>. ' +
          'Please upgrade to 2.7 or above.'
      )
    }
    return descriptor.script
  }

  const isProd =
    loaderContext.mode === 'production' || process.env.NODE_ENV === 'production'
  const isServer = options.optimizeSSR || loaderContext.target === 'node'

  const cacheToUse = isServer ? serverCache : clientCache
  const cached = cacheToUse.get(descriptor)
  if (cached) {
    return cached
  }

  let resolved = null

  try {
    resolved = compiler.compileScript(descriptor, {
      id: scopeId,
      isProd,
      babelParserPlugins: options.babelParserPlugins
    })
  } catch (e) {
    loaderContext.emitError(e)
  }

  cacheToUse.set(descriptor, resolved)
  return resolved
}


code:
/* globals __VUE_SSR_CONTEXT__ */

// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).
// This module is a runtime utility for cleaner component module output and will
// be included in the final webpack user bundle.

export default function normalizeComponent(
  scriptExports,
  render,
  staticRenderFns,
  functionalTemplate,
  injectStyles,
  scopeId,
  moduleIdentifier /* server only */,
  shadowMode /* vue-cli only */
) {
  // Vue.extend constructor export interop
  var options =
    typeof scriptExports === 'function' ? scriptExports.options : scriptExports

  // render functions
  if (render) {
    options.render = render
    options.staticRenderFns = staticRenderFns
    options._compiled = true
  }

  // functional template
  if (functionalTemplate) {
    options.functional = true
  }

  // scopedId
  if (scopeId) {
    options._scopeId = 'data-v-' + scopeId
  }

  var hook
  if (moduleIdentifier) {
    // server build
    hook = function (context) {
      // 2.3 injection
      context =
        context || // cached call
        (this.$vnode && this.$vnode.ssrContext) || // stateful
        (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional
      // 2.2 with runInNewContext: true
      if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
        context = __VUE_SSR_CONTEXT__
      }
      // inject component styles
      if (injectStyles) {
        injectStyles.call(this, context)
      }
      // register component module identifier for async chunk inferrence
      if (context && context._registeredComponents) {
        context._registeredComponents.add(moduleIdentifier)
      }
    }
    // used by ssr in case component is cached and beforeCreate
    // never gets called
    options._ssrRegister = hook
  } else if (injectStyles) {
    hook = shadowMode
      ? function () {
          injectStyles.call(
            this,
            (options.functional ? this.parent : this).$root.$options.shadowRoot
          )
        }
      : injectStyles
  }

  if (hook) {
    if (options.functional) {
      // for template-only hot-reload because in that case the render fn doesn't
      // go through the normalizer
      options._injectStyles = hook
      // register for functional component in vue file
      var originalRender = options.render
      options.render = function renderWithStyleInjection(h, context) {
        hook.call(context)
        return originalRender(h, context)
      }
    } else {
      // inject component registration as beforeCreate hook
      var existing = options.beforeCreate
      options.beforeCreate = existing ? [].concat(existing, hook) : [hook]
    }
  }

  return {
    exports: scriptExports,
    options: options
  }
}


code:
const { resolveScript } = require('./resolveScript')

module.exports = function selectBlock(
  descriptor,
  scopeId,
  options,
  loaderContext,
  query,
  appendExtension
) {
  // template
  if (query.type === `template`) {
    if (appendExtension) {
      loaderContext.resourcePath += '.' + (descriptor.template.lang || 'html')
    }
    loaderContext.callback(
      null,
      descriptor.template.content,
      descriptor.template.map
    )
    return
  }

  // script
  if (query.type === `script`) {
    const script = resolveScript(descriptor, scopeId, options, loaderContext)
    if (appendExtension) {
      loaderContext.resourcePath += '.' + (script.lang || 'js')
    }
    loaderContext.callback(null, script.content, script.map)
    return
  }

  // styles
  if (query.type === `style` && query.index != null) {
    const style = descriptor.styles[query.index]
    if (appendExtension) {
      loaderContext.resourcePath += '.' + (style.lang || 'css')
    }
    loaderContext.callback(null, style.content, style.map)
    return
  }

  // custom
  if (query.type === 'custom' && query.index != null) {
    const block = descriptor.customBlocks[query.index]
    loaderContext.callback(null, block.content, block.map)
    return
  }
}


code:
# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false


code:
# 1.0.2 Quick Sort

- Sorts object keys so that property order doesn't affect outcome

# 1.0.1 Perfect Circle

- Guard against circular references

# 1.0.0 IPO

- Initial Public Release


code:
'use strict';

function pad (hash, len) {
  while (hash.length < len) {
    hash = '0' + hash;
  }
  return hash;
}

function fold (hash, text) {
  var i;
  var chr;
  var len;
  if (text.length === 0) {
    return hash;
  }
  for (i = 0, len = text.length; i < len; i++) {
    chr = text.charCodeAt(i);
    hash = ((hash << 5) - hash) + chr;
    hash |= 0;
  }
  return hash < 0 ? hash * -2 : hash;
}

function foldObject (hash, o, seen) {
  return Object.keys(o).sort().reduce(foldKey, hash);
  function foldKey (hash, key) {
    return foldValue(hash, o[key], key, seen);
  }
}

function foldValue (input, value, key, seen) {
  var hash = fold(fold(fold(input, key), toString(value)), typeof value);
  if (value === null) {
    return fold(hash, 'null');
  }
  if (value === undefined) {
    return fold(hash, 'undefined');
  }
  if (typeof value === 'object') {
    if (seen.indexOf(value) !== -1) {
      return fold(hash, '[Circular]' + key);
    }
    seen.push(value);
    return foldObject(hash, value, seen);
  }
  return fold(hash, value.toString());
}

function toString (o) {
  return Object.prototype.toString.call(o);
}

function sum (o) {
  return pad(foldValue(0, o, '', []).toString(16), 8);
}

module.exports = sum;


hash-sum

description: Blazing fast unique hash generator

license: MIT

type: git

test: jshint . && tape test.js


code:
# hash-sum

> blazing fast unique hash generator

# install

```shell
npm i hash-sum -S
```

# features

- no dependencies
- minimal footprint
- works in all of node.js, io.js, and the browser
- hashes functions based on their source code
- produces different hashes for different object types
- support for circular references in objects
- ignores property assignment order

# `sum(value)`

yields a four-byte hexadecimal hash based off of `value`.

```
# creates unique hashes
 creates unique hashes
4d237d49 from: [ 0, 1, 2, 3 ]
766ec173 from: { url: 12 }
2f473108 from: { headers: 12 }
23308836 from: { headers: 122 }
062bce44 from: { headers: '122' }
acb9f66e from: { headers: { accept: 'text/plain' } }
1c365a2d from: { payload: [ 0, 1, 2, 3 ], headers: [ { a: 'b' } ] }
7319ae9d from: { a: [Function] }
8a3a0e86 from: { b: [Function] }
b6d7f5d4 from: { b: [Function] }
6c95fc65 from: function () {}
2941766e from: function (a) {}
294f8def from: function (b) {}
2d9c0cb8 from: function (a) { return a;}
ed5c63fc from: function (a) {return a;}
bba68bf6 from: ''
2d27667d from: 'null'
774b96ed from: 'false'
2d2a1684 from: 'true'
8daa1a0c from: '0'
8daa1a0a from: '1'
e38f07cc from: 'void 0'
6037ea1a from: 'undefined'
9b7df12e from: null
3c206f76 from: false
01e34ba8 from: true
1a96284a from: 0
1a96284b from: 1
29172c1a from: undefined
4505230f from: {}
3718c6e8 from: { a: {}, b: {} }
5d844489 from: []
938eaaf0 from: Tue Jul 14 2015 15:35:36 GMT-0300 (ART)
dfe5fb2e from: global
ok 1 should be equal
```

# license

MIT


code:
'use strict';

var _ = require('lodash');
var test = require('tape');
var sum = require('./');

test('creates unique hashes', function (t) {
  var results = [];
  sub([0,1,2,3]);
  sub({url:12});
  sub({headers:12});
  sub({headers:122});
  sub({headers:'122'});
  sub({headers:{accept:'text/plain'}});
  sub({payload:[0,1,2,3],headers:[{a:'b'}]});
  sub({a:function () {}});
  sub({b:function () {}});
  sub({b:function (a) {}});
  sub(function () {});
  sub(function (a) {});
  sub(function (b) {});
  sub(function (a) { return a;});
  sub(function (a) {return a;});
  sub('');
  sub('null');
  sub('false');
  sub('true');
  sub('0');
  sub('1');
  sub('void 0');
  sub('undefined');
  sub(null);
  sub(false);
  sub(true);
  sub(0);
  sub(1);
  sub(void 0);
  sub({});
  sub({a:{},b:{}});
  sub([]);
  sub(new Date());
  sub(global, 'global');
  t.equal(results.length, _.uniq(results).length);
  t.end();

  function sub (value, name) {
    var hash = sum(value);
    results.push(hash);
    console.log('%s from:', hash, name || value);
  }
});

test('hashes clash if same properties', function (t) {
  equals({a:'1'},{a:'1'});
  equals({a:'1',b:1},{b:1,a:'1'});
  t.end();

  function equals (a, b) {
    t.equal(sum(a), sum(b));
  }
});


vue-loader

description: Vue single-file component loader for Webpack

author: Evan You

pre-commit: lint-staged

lib/**/*.js:
eslint --fix
git add

test/**/*.js:
eslint --fix
git add

test: jest --env node

test:match-resource: cross-env INLINE_MATCH_RESOURCE=true jest --env node

lint: eslint lib test --fix

build: webpack --config example/webpack.config.js --hide-modules

dev: webpack-dev-server --config example/webpack.config.js --inline --hot

docs: vuepress dev docs

docs:build: vuepress build docs


code:
# @vue/web-component-wrapper [![CircleCI](https://circleci.com/gh/vuejs/vue-web-component-wrapper.svg?style=shield)](https://circleci.com/gh/vuejs/vue-web-component-wrapper)

> Wrap and register a Vue component as a custom element.

## Compatibility

**[Requires ES2015 classes](https://caniuse.com/es6-class). IE11 and below not supported.**

- **If targeting browsers that natively support ES2015, but not native Web Components:**

  You will also need the [Shady DOM + Custom Elements polyfill](https://github.com/webcomponents/webcomponentsjs).

  See caniuse.com for support on [Custom Elements v1](https://caniuse.com/#feat=custom-elementsv1) and [Shadow DOM v1](https://caniuse.com/#feat=shadowdomv1).

- **Note on CSS Encapsulation When Using the Shady DOM polyfill**

  It's recommended to use [CSS Modules](https://vue-loader.vuejs.org/en/features/css-modules.html) instead of `<style scoped>` in your `*.vue` files if you intend to use the Shady DOM polyfill, because it does not offer real style encapsulation like Shadow DOM does, so external stylesheets may affect your components if not using hashed class names.

- **If targeting browsers that does not support ES2015:**

  You might want to reconsider since you'll be better off not using Web Components in this case.

## Usage

- **`dist/vue-wc-wrapper.js`**: This file is in ES modules format. It's the default export for bundlers, and can be used in browsers with `<script type="module">`.

- **`dist/vue-wc-wrapper.global.js`**: This is for old school `<script>` includes in browsers that do not support `<script type="module">` yet (exposes `wrapVueWebComponent` global).

``` js
import Vue from 'vue'
import wrap from '@vue/web-component-wrapper'

const Component = {
  // any component options
}

const CustomElement = wrap(Vue, Component)

window.customElements.define('my-element', CustomElement)
```

It works with async components as well - you can pass an async component factory function that returns a Promise, and the function will only be called when an instance of the custom element is created on the page:

``` js
const CustomElement = wrap(Vue, () => import(`MyComponent.vue`))

window.customElements.define('my-element', CustomElement)
```

## Interface Proxying Details

### Props

- All `props` declared in the Vue component are exposed on the custom element as its properties. Kebab-case props are converted to camelCase properties, similar to how they are converted in Vue.

- Setting properties on the custom element updates the props passed to the inner Vue component.

- Setting attributes on the custom element updates corresponding declared props. Attributes are mapped to kebab-case. For example, a prop named `someProp` will have a corresponding attribute named `some-prop`.

- Attributes that map to props declared with `type: Boolean` are auto-casted into boolean values in the following rules:

  - `""` or same value as attribute name: -> `true`

  - `"true"` -> `true`

  - `"false"` -> `false`

- Attributes that map to props declared with `type: Number` are auto-casted into numbers if the value is a parsable number.

### Events

Custom events emitted on the inner Vue component are dispatched on the custom element as a `CustomEvent`. Additional arguments passed to `$emit` will be exposed as an Array as `event.detail`.

### Slots

Slots work the same way as expected, including named slots. They also update when changed (using `MutationObserver`).

Scoped slots however, are not supported as they are a Vue specific concept.

### Lifecycle

When the custom element is removed from the document, the Vue component behaves just as if it's inside a `<keep-alive>` and its `deactivated` hook will be called. When it's inserted again, the `activated` hook will be called.

If you wish to destroy the inner component, you'd have to do that explicitly:

``` js
myElement.vueComponent.$destroy()
```

## Acknowledgments

Special thanks to the prior work by @karol-f in [vue-custom-element](https://github.com/karol-f/vue-custom-element).

## License

MIT


code:
var wrapVueWebComponent = (function () {
'use strict';

const camelizeRE = /-(\w)/g;
const camelize = str => {
  return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
};

const hyphenateRE = /\B([A-Z])/g;
const hyphenate = str => {
  return str.replace(hyphenateRE, '-$1').toLowerCase()
};

function getInitialProps (propsList) {
  const res = {};
  propsList.forEach(key => {
    res[key] = undefined;
  });
  return res
}

function injectHook (options, key, hook) {
  options[key] = [].concat(options[key] || []);
  options[key].unshift(hook);
}

function callHooks (vm, hook) {
  if (vm) {
    const hooks = vm.$options[hook] || [];
    hooks.forEach(hook => {
      hook.call(vm);
    });
  }
}

function createCustomEvent (name, args) {
  return new CustomEvent(name, {
    bubbles: false,
    cancelable: false,
    detail: args
  })
}

const isBoolean = val => /function Boolean/.test(String(val));
const isNumber = val => /function Number/.test(String(val));

function convertAttributeValue (value, name, { type } = {}) {
  if (isBoolean(type)) {
    if (value === 'true' || value === 'false') {
      return value === 'true'
    }
    if (value === '' || value === name || value != null) {
      return true
    }
    return value
  } else if (isNumber(type)) {
    const parsed = parseFloat(value, 10);
    return isNaN(parsed) ? value : parsed
  } else {
    return value
  }
}

function toVNodes (h, children) {
  const res = [];
  for (let i = 0, l = children.length; i < l; i++) {
    res.push(toVNode(h, children[i]));
  }
  return res
}

function toVNode (h, node) {
  if (node.nodeType === 3) {
    return node.data.trim() ? node.data : null
  } else if (node.nodeType === 1) {
    const data = {
      attrs: getAttributes(node),
      domProps: {
        innerHTML: node.innerHTML
      }
    };
    if (data.attrs.slot) {
      data.slot = data.attrs.slot;
      delete data.attrs.slot;
    }
    return h(node.tagName, data)
  } else {
    return null
  }
}

function getAttributes (node) {
  const res = {};
  for (let i = 0, l = node.attributes.length; i < l; i++) {
    const attr = node.attributes[i];
    res[attr.nodeName] = attr.nodeValue;
  }
  return res
}

function wrap (Vue, Component) {
  const isAsync = typeof Component === 'function' && !Component.cid;
  let isInitialized = false;
  let hyphenatedPropsList;
  let camelizedPropsList;
  let camelizedPropsMap;

  function initialize (Component) {
    if (isInitialized) return

    const options = typeof Component === 'function'
      ? Component.options
      : Component;

    // extract props info
    const propsList = Array.isArray(options.props)
      ? options.props
      : Object.keys(options.props || {});
    hyphenatedPropsList = propsList.map(hyphenate);
    camelizedPropsList = propsList.map(camelize);
    const originalPropsAsObject = Array.isArray(options.props) ? {} : options.props || {};
    camelizedPropsMap = camelizedPropsList.reduce((map, key, i) => {
      map[key] = originalPropsAsObject[propsList[i]];
      return map
    }, {});

    // proxy $emit to native DOM events
    injectHook(options, 'beforeCreate', function () {
      const emit = this.$emit;
      this.$emit = (name, ...args) => {
        this.$root.$options.customElement.dispatchEvent(createCustomEvent(name, args));
        return emit.call(this, name, ...args)
      };
    });

    injectHook(options, 'created', function () {
      // sync default props values to wrapper on created
      camelizedPropsList.forEach(key => {
        this.$root.props[key] = this[key];
      });
    });

    // proxy props as Element properties
    camelizedPropsList.forEach(key => {
      Object.defineProperty(CustomElement.prototype, key, {
        get () {
          return this._wrapper.props[key]
        },
        set (newVal) {
          this._wrapper.props[key] = newVal;
        },
        enumerable: false,
        configurable: true
      });
    });

    isInitialized = true;
  }

  function syncAttribute (el, key) {
    const camelized = camelize(key);
    const value = el.hasAttribute(key) ? el.getAttribute(key) : undefined;
    el._wrapper.props[camelized] = convertAttributeValue(
      value,
      key,
      camelizedPropsMap[camelized]
    );
  }

  class CustomElement extends HTMLElement {
    constructor () {
      const self = super();
      self.attachShadow({ mode: 'open' });

      const wrapper = self._wrapper = new Vue({
        name: 'shadow-root',
        customElement: self,
        shadowRoot: self.shadowRoot,
        data () {
          return {
            props: {},
            slotChildren: []
          }
        },
        render (h) {
          return h(Component, {
            ref: 'inner',
            props: this.props
          }, this.slotChildren)
        }
      });

      // Use MutationObserver to react to future attribute & slot content change
      const observer = new MutationObserver(mutations => {
        let hasChildrenChange = false;
        for (let i = 0; i < mutations.length; i++) {
          const m = mutations[i];
          if (isInitialized && m.type === 'attributes' && m.target === self) {
            syncAttribute(self, m.attributeName);
          } else {
            hasChildrenChange = true;
          }
        }
        if (hasChildrenChange) {
          wrapper.slotChildren = Object.freeze(toVNodes(
            wrapper.$createElement,
            self.childNodes
          ));
        }
      });
      observer.observe(self, {
        childList: true,
        subtree: true,
        characterData: true,
        attributes: true
      });
    }

    get vueComponent () {
      return this._wrapper.$refs.inner
    }

    connectedCallback () {
      const wrapper = this._wrapper;
      if (!wrapper._isMounted) {
        // initialize attributes
        const syncInitialAttributes = () => {
          wrapper.props = getInitialProps(camelizedPropsList);
          hyphenatedPropsList.forEach(key => {
            syncAttribute(this, key);
          });
        };

        if (isInitialized) {
          syncInitialAttributes();
        } else {
          // async & unresolved
          Component().then(resolved => {
            if (resolved.__esModule || resolved[Symbol.toStringTag] === 'Module') {
              resolved = resolved.default;
            }
            initialize(resolved);
            syncInitialAttributes();
          });
        }
        // initialize children
        wrapper.slotChildren = Object.freeze(toVNodes(
          wrapper.$createElement,
          this.childNodes
        ));
        wrapper.$mount();
        this.shadowRoot.appendChild(wrapper.$el);
      } else {
        callHooks(this.vueComponent, 'activated');
      }
    }

    disconnectedCallback () {
      callHooks(this.vueComponent, 'deactivated');
    }
  }

  if (!isAsync) {
    initialize(Component);
  }

  return CustomElement
}

return wrap;

}());


code:
const camelizeRE = /-(\w)/g;
const camelize = str => {
  return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
};

const hyphenateRE = /\B([A-Z])/g;
const hyphenate = str => {
  return str.replace(hyphenateRE, '-$1').toLowerCase()
};

function getInitialProps (propsList) {
  const res = {};
  propsList.forEach(key => {
    res[key] = undefined;
  });
  return res
}

function injectHook (options, key, hook) {
  options[key] = [].concat(options[key] || []);
  options[key].unshift(hook);
}

function callHooks (vm, hook) {
  if (vm) {
    const hooks = vm.$options[hook] || [];
    hooks.forEach(hook => {
      hook.call(vm);
    });
  }
}

function createCustomEvent (name, args) {
  return new CustomEvent(name, {
    bubbles: false,
    cancelable: false,
    detail: args
  })
}

const isBoolean = val => /function Boolean/.test(String(val));
const isNumber = val => /function Number/.test(String(val));

function convertAttributeValue (value, name, { type } = {}) {
  if (isBoolean(type)) {
    if (value === 'true' || value === 'false') {
      return value === 'true'
    }
    if (value === '' || value === name || value != null) {
      return true
    }
    return value
  } else if (isNumber(type)) {
    const parsed = parseFloat(value, 10);
    return isNaN(parsed) ? value : parsed
  } else {
    return value
  }
}

function toVNodes (h, children) {
  const res = [];
  for (let i = 0, l = children.length; i < l; i++) {
    res.push(toVNode(h, children[i]));
  }
  return res
}

function toVNode (h, node) {
  if (node.nodeType === 3) {
    return node.data.trim() ? node.data : null
  } else if (node.nodeType === 1) {
    const data = {
      attrs: getAttributes(node),
      domProps: {
        innerHTML: node.innerHTML
      }
    };
    if (data.attrs.slot) {
      data.slot = data.attrs.slot;
      delete data.attrs.slot;
    }
    return h(node.tagName, data)
  } else {
    return null
  }
}

function getAttributes (node) {
  const res = {};
  for (let i = 0, l = node.attributes.length; i < l; i++) {
    const attr = node.attributes[i];
    res[attr.nodeName] = attr.nodeValue;
  }
  return res
}

function wrap (Vue, Component) {
  const isAsync = typeof Component === 'function' && !Component.cid;
  let isInitialized = false;
  let hyphenatedPropsList;
  let camelizedPropsList;
  let camelizedPropsMap;

  function initialize (Component) {
    if (isInitialized) return

    const options = typeof Component === 'function'
      ? Component.options
      : Component;

    // extract props info
    const propsList = Array.isArray(options.props)
      ? options.props
      : Object.keys(options.props || {});
    hyphenatedPropsList = propsList.map(hyphenate);
    camelizedPropsList = propsList.map(camelize);
    const originalPropsAsObject = Array.isArray(options.props) ? {} : options.props || {};
    camelizedPropsMap = camelizedPropsList.reduce((map, key, i) => {
      map[key] = originalPropsAsObject[propsList[i]];
      return map
    }, {});

    // proxy $emit to native DOM events
    injectHook(options, 'beforeCreate', function () {
      const emit = this.$emit;
      this.$emit = (name, ...args) => {
        this.$root.$options.customElement.dispatchEvent(createCustomEvent(name, args));
        return emit.call(this, name, ...args)
      };
    });

    injectHook(options, 'created', function () {
      // sync default props values to wrapper on created
      camelizedPropsList.forEach(key => {
        this.$root.props[key] = this[key];
      });
    });

    // proxy props as Element properties
    camelizedPropsList.forEach(key => {
      Object.defineProperty(CustomElement.prototype, key, {
        get () {
          return this._wrapper.props[key]
        },
        set (newVal) {
          this._wrapper.props[key] = newVal;
        },
        enumerable: false,
        configurable: true
      });
    });

    isInitialized = true;
  }

  function syncAttribute (el, key) {
    const camelized = camelize(key);
    const value = el.hasAttribute(key) ? el.getAttribute(key) : undefined;
    el._wrapper.props[camelized] = convertAttributeValue(
      value,
      key,
      camelizedPropsMap[camelized]
    );
  }

  class CustomElement extends HTMLElement {
    constructor () {
      const self = super();
      self.attachShadow({ mode: 'open' });

      const wrapper = self._wrapper = new Vue({
        name: 'shadow-root',
        customElement: self,
        shadowRoot: self.shadowRoot,
        data () {
          return {
            props: {},
            slotChildren: []
          }
        },
        render (h) {
          return h(Component, {
            ref: 'inner',
            props: this.props
          }, this.slotChildren)
        }
      });

      // Use MutationObserver to react to future attribute & slot content change
      const observer = new MutationObserver(mutations => {
        let hasChildrenChange = false;
        for (let i = 0; i < mutations.length; i++) {
          const m = mutations[i];
          if (isInitialized && m.type === 'attributes' && m.target === self) {
            syncAttribute(self, m.attributeName);
          } else {
            hasChildrenChange = true;
          }
        }
        if (hasChildrenChange) {
          wrapper.slotChildren = Object.freeze(toVNodes(
            wrapper.$createElement,
            self.childNodes
          ));
        }
      });
      observer.observe(self, {
        childList: true,
        subtree: true,
        characterData: true,
        attributes: true
      });
    }

    get vueComponent () {
      return this._wrapper.$refs.inner
    }

    connectedCallback () {
      const wrapper = this._wrapper;
      if (!wrapper._isMounted) {
        // initialize attributes
        const syncInitialAttributes = () => {
          wrapper.props = getInitialProps(camelizedPropsList);
          hyphenatedPropsList.forEach(key => {
            syncAttribute(this, key);
          });
        };

        if (isInitialized) {
          syncInitialAttributes();
        } else {
          // async & unresolved
          Component().then(resolved => {
            if (resolved.__esModule || resolved[Symbol.toStringTag] === 'Module') {
              resolved = resolved.default;
            }
            initialize(resolved);
            syncInitialAttributes();
          });
        }
        // initialize children
        wrapper.slotChildren = Object.freeze(toVNodes(
          wrapper.$createElement,
          this.childNodes
        ));
        wrapper.$mount();
        this.shadowRoot.appendChild(wrapper.$el);
      } else {
        callHooks(this.vueComponent, 'activated');
      }
    }

    disconnectedCallback () {
      callHooks(this.vueComponent, 'deactivated');
    }
  }

  if (!isAsync) {
    initialize(Component);
  }

  return CustomElement
}

export default wrap;


@vue/web-component-wrapper

description: wrap a vue component as a web component.

test: jest

lint: eslint src

build: rollup -c

prepare: rollup -c

test:types: tsc -p ./types/tsconfig.json

keywords: vue web-component

*.js:
eslint --fix
git add


code:
import _Vue, { Component, AsyncComponent } from 'vue'

declare function wrap(
  Vue: typeof _Vue,
  Component: Component | AsyncComponent
): HTMLElement

export default wrap


code:
Collection of essential Vue Composition Utilities

## 🚀 Features

- 🎪 [**Interactive docs & demos**](https://vueuse.org)
- 🕶 **Seamless migration**: Works for **both** Vue 3 and 2
- ⚡ **Fully tree shakeable**: Only take what you want, [bundle size](https://vueuse.org/export-size)
- 🦾 **Type Strong**: Written in [TypeScript](https://www.typescriptlang.org/), with [TS Docs](https://github.com/microsoft/tsdoc)
- 🔋 **SSR Friendly**
- 🌎 **No bundler required**: Usable via CDN
- 🔩 **Flexible**: Configurable event filters and targets
- 🔌 **Optional [Add-ons](https://vueuse.org/add-ons)**: Router, Firebase, RxJS, etc.

## 🦄 Usage

```ts
import { useLocalStorage, useMouse, usePreferredDark } from '@vueuse/core'

export default {
  setup() {
    // tracks mouse position
    const { x, y } = useMouse()

    // is user prefers dark theme
    const isDark = usePreferredDark()

    // persist state in localStorage
    const store = useLocalStorage(
      'my-storage',
      {
        name: 'Apple',
        color: 'red',
      },
    )

    return { x, y, isDark, store }
  },
}
```

Refer to [functions list](https://vueuse.org/functions) or [documentations](https://vueuse.org/) for more details.

## 📦 Install

> 🎩 From v4.0, it works for Vue 2 & 3 **within a single package** by the power of [vue-demi](https://github.com/vueuse/vue-demi)!

```bash
npm i @vueuse/core
```

[Add ons](https://vueuse.org/add-ons.html) | [Nuxt Module](https://vueuse.org/guide/index.html#nuxt)

> From v6.0, VueUse requires `vue` >= v3.2 or `@vue/composition-api` >= v1.1

###### Demos

- [Vite + Vue 3](https://github.com/vueuse/vueuse-vite-starter)
- [Nuxt 3 + Vue 3](https://github.com/antfu/vitesse-nuxt3)
- [Webpack + Vue 3](https://github.com/vueuse/vueuse-vue3-example)
- [Nuxt 2 + Vue 2](https://github.com/antfu/vitesse-nuxt-bridge)
- [Vue CLI + Vue 2](https://github.com/vueuse/vueuse-vue2-example)

### CDN

```html
<script src="https://unpkg.com/@vueuse/shared"></script>
<script src="https://unpkg.com/@vueuse/core"></script>
```

It will be exposed to global as `window.VueUse`

## 🪴 Project Activity

![Alt](https://repobeats.axiom.co/api/embed/a406ba7461a6a087dbdb14d4395046c948d44c51.svg "Repobeats analytics image")

## 🧱 Contribute

See the [**Contributing Guide**](https://vueuse.org/contributing)

## 🌸 Thanks

This project is heavily inspired by the following awesome projects.

- [streamich/react-use](https://github.com/streamich/react-use)
- [u3u/vue-hooks](https://github.com/u3u/vue-hooks)
- [logaretm/vue-use-web](https://github.com/logaretm/vue-use-web)
- [kripod/react-hooks](https://github.com/kripod/react-hooks)

And thanks to [all the contributors on GitHub](https://github.com/vueuse/vueuse/graphs/contributors)!

## 👨🚀 Contributors

### Financial Contributors on Open Collective

## 📄 License

[MIT License](https://github.com/vueuse/vueuse/blob/main/LICENSE) © 2019-PRESENT [Anthony Fu](https://github.com/antfu)