vite#normalizePath TypeScript Examples

The following examples show how to use vite#normalizePath. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: config.ts    From vite-tsconfig-paths with MIT License 6 votes vote down vote up
export function loadConfig(cwd: string): Config | undefined {
  const configPath = resolveConfigPath(cwd)
  if (configPath) {
    const config = loadTsconfig(configPath) as TSConfig
    const {
      compilerOptions: { allowJs, checkJs, baseUrl, paths, outDir } = {},
    } = config

    return {
      configPath: normalizePath(configPath),
      include: config.include,
      exclude: config.exclude,
      allowJs: allowJs || checkJs,
      baseUrl: baseUrl && normalizePath(resolve(configPath, '..', baseUrl)),
      paths,
      outDir,
    }
  }
}
Example #2
Source File: index.ts    From vite-tsconfig-paths with MIT License 6 votes vote down vote up
function findProjects(viteRoot: string, opts: PluginOptions) {
  const root = opts.root
    ? resolve(viteRoot, normalizePath(opts.root))
    : viteRoot

  let { projects } = opts
  if (!projects) {
    debug(`crawling "${root}"`)
    projects = crawl(root, {
      only: ['jsconfig.json', 'tsconfig.json'],
      skip: ['node_modules', '.git'],
    })
  }

  // Calculate the depth of each project path.
  const depthMap: { [path: string]: number } = {}
  projects = projects.map((projectPath) => {
    projectPath = resolve(root, normalizePath(projectPath))
    depthMap[projectPath] =
      projectPath.split('/').length - (projectPath.endsWith('.json') ? 1 : 0)
    return projectPath
  })

  // Ensure deeper projects take precedence.
  return projects.sort((a, b) => depthMap[b] - depthMap[a])
}
Example #3
Source File: path.ts    From vite-tsconfig-paths with MIT License 5 votes vote down vote up
resolve = isWindows
  ? (...paths: string[]) => normalizePath(path.win32.resolve(...paths))
  : path.posix.resolve
Example #4
Source File: index.ts    From vite-plugin-mdx with MIT License 4 votes vote down vote up
/**
 * With transclusion enabled, an `.mdx` file can import other `.mdx` or `.md`
 * files without an import specifier.
 *
 *     import "../other.mdx"
 *
 * The file extension is required.
 *
 * The imported file is inlined into its importer, but the imported file can
 * still have its own Remark plugins.
 *
 */
export function viteMdxTransclusion(
  globalMdxOptions: MdxPlugin['mdxOptions'],
  getMdxOptions?: (filename: string) => MdxOptions
): Plugin {
  /**
   * To recompile an importer when its transcluded files are changed,
   * we need to track the relationships between them.
   */
  let importMap: ImportMap
  /**
   * To avoid redundant parsing and processing, we cache the MDX syntax trees
   * of transcluded files to serve as a fast path when an importer is recompiled.
   */
  let astCache: MdxAstCache

  return {
    name: 'mdx:transclusion',
    configResolved({ root, logger }) {
      let watcher: FSWatcher | undefined

      this.configureServer = (server) => {
        watcher = server.watcher
        importMap = new ImportMap()
        astCache = new LRUCache({
          maxAge: 30 * 6e4, // 30 minutes
          maxSize: 100
        })

        // When a transcluded file changes, recompile its importers.
        // Also, clean up the import map when an importer is deleted.
        watcher.on('all', (event, filePath) => {
          if (/\.mdx?$/.test(filePath)) {
            if (event === 'unlink') {
              importMap.deleteImporter(filePath)
            }
            const importers = importMap.importers.get(filePath)
            if (importers) {
              astCache.delete(filePath)
              importers.forEach((importer) => {
                watcher!.emit('change', importer)
              })
            }
          }
        })
      }

      this.buildStart = function () {
        globalMdxOptions.remarkPlugins.push(
          remarkTransclusion({
            astCache,
            importMap,
            resolve: async (id, importer) => {
              const resolved = await this.resolve(id, importer)
              if (resolved) {
                id = normalizePath(resolved.id)
                // Ensure files outside the Vite project root are watched.
                if (watcher && isAbsolute(id) && !id.startsWith(root + '/')) {
                  watcher.add(id)
                }
                return id
              }
              logger.warn(`Failed to resolve "${id}" imported by "${importer}"`)
            },
            readFile: (filePath) => fs.promises.readFile(filePath, 'utf8'),
            getCompiler: (filePath) =>
              createMdxAstCompiler(
                root,
                mergeArrays(
                  globalMdxOptions.remarkPlugins,
                  getMdxOptions?.(filePath).remarkPlugins
                )
              )
          })
        )
      }
    }
  }
}
Example #5
Source File: index.ts    From vite-plugin-vue-i18n with MIT License 4 votes vote down vote up
function pluginI18n(
  options: VitePluginVueI18nOptions = { forceStringify: false }
): Plugin {
  debug('plugin options:', options)

  // use `normalizePath` for `options.include`
  let include = options.include
  if (include) {
    if (isArray(include)) {
      include = include.map(item => normalizePath(item))
    } else if (isString(include)) {
      include = normalizePath(include)
    }
  }

  const filter = createFilter(include)
  const runtimeOnly = isBoolean(options.runtimeOnly)
    ? options.runtimeOnly
    : true
  const compositionOnly = isBoolean(options.compositionOnly)
    ? options.compositionOnly
    : true
  const fullIinstall = isBoolean(options.fullInstall)
    ? options.fullInstall
    : true
  const defaultSFCLang = isString(options.defaultSFCLang)
    ? options.defaultSFCLang
    : undefined
  const globalSFCScope = isBoolean(options.globalSFCScope)
    ? options.globalSFCScope
    : false
  let config: ResolvedConfig | null = null

  return {
    name: 'vite-plugin-vue-i18n',

    config(config: UserConfig, { command }) {
      if (command === 'build' && runtimeOnly) {
        normalizeConfigResolveAliias(config)
        if (isArray(config.resolve!.alias)) {
          config.resolve!.alias.push({
            find: 'vue-i18n',
            replacement: 'vue-i18n/dist/vue-i18n.runtime.esm-bundler.js'
          })
        } else {
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
          ;(config.resolve!.alias as any)['vue-i18n'] =
            'vue-i18n/dist/vue-i18n.runtime.esm-bundler.js'
        }
        debug('set vue-i18n runtime only')
      }

      config.define = config.define || {}
      config.define['__VUE_I18N_LEGACY_API__'] = !compositionOnly
      debug(
        `set __VUE_I18N_LEGACY_API__ is '${config.define['__VUE_I18N_LEGACY_API__']}'`
      )

      config.define['__VUE_I18N_FULL_INSTALL__'] = fullIinstall
      debug(
        `set __VUE_I18N_FULL_INSTALL__ is '${config.define['__VUE_I18N_FULL_INSTALL__']}'`
      )

      config.define['__VUE_I18N_PROD_DEVTOOLS__'] = false
    },

    configResolved(_config: ResolvedConfig) {
      // store config
      config = _config

      // json transform handling
      const jsonPlugin = config.plugins.find(p => p.name === 'vite:json')
      if (jsonPlugin) {
        const orgTransform = jsonPlugin.transform // backup @rollup/plugin-json
        jsonPlugin.transform = async function (code: string, id: string) {
          if (!/\.json$/.test(id)) {
            return null
          }
          if (filter(id)) {
            const map = this.getCombinedSourcemap()
            debug('override json plugin', code, map)
            return Promise.resolve({
              code,
              map
            })
          } else {
            debug('org json plugin')
            return orgTransform!.apply(this, [code, id])
          }
        }
      }
    },

    resolveId(id: string) {
      if (id === INTLIFY_BUNDLE_IMPORT_ID) {
        return id
      }
    },

    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    async load(id: string, ssr: boolean) {
      if (id === INTLIFY_BUNDLE_IMPORT_ID && include) {
        let resourcePaths = [] as string[]
        const includePaths = isArray(include) ? include : [include]
        for (const inc of includePaths) {
          resourcePaths = [...(await fg(inc))]
        }
        // TODO: source-map
        const code = await generateBundleResources(
          resourcePaths,
          config != null ? config.isProduction : false,
          options.forceStringify!
        )
        return Promise.resolve(code)
      }
    },

    async handleHotUpdate({ file, server }) {
      if (/\.(json5?|ya?ml)$/.test(file)) {
        const module = server.moduleGraph.getModuleById(
          INTLIFY_BUNDLE_IMPORT_ID
        )
        if (module) {
          server.moduleGraph.invalidateModule(module)
          return [module!]
        }
      }
    },

    async transform(code: string, id: string) {
      const { filename, query } = parseVueRequest(id)
      debug('transform', id, JSON.stringify(query))

      const parseOptions = getOptions(
        filename,
        config != null ? config.isProduction : false,
        query as Record<string, unknown>,
        options.forceStringify
      ) as CodeGenOptions
      debug('parseOptions', parseOptions)

      let langInfo = 'json'
      if (!query.vue) {
        if (/\.(json5?|ya?ml)$/.test(id) && filter(id)) {
          langInfo = path.parse(filename).ext
          // NOTE:
          // `.json` is handled default in vite, and it's transformed to JS object.
          let _source = code
          if (langInfo === '.json') {
            _source = await getRaw(id)
          }
          const generate = /\.?json5?/.test(langInfo)
            ? generateJSON
            : generateYAML
          const { code: generatedCode } = generate(_source, parseOptions)
          debug('generated code', generatedCode)
          // TODO: error handling & sourcempa
          return Promise.resolve(generatedCode)
        } else {
          return Promise.resolve(code)
        }
      } else {
        // for Vue SFC
        if (isCustomBlock(query as Record<string, unknown>)) {
          if ('src' in query) {
            if (isString(query.lang)) {
              langInfo = query.lang === 'i18n' ? 'json' : query.lang
            } else if (defaultSFCLang) {
              langInfo = defaultSFCLang
            }
          } else {
            if (isString(query.lang)) {
              langInfo = query.lang
            } else if (defaultSFCLang) {
              langInfo = defaultSFCLang
            }
          }
          if (!parseOptions.isGlobal && globalSFCScope) {
            parseOptions.isGlobal = true
          }
          const generate = /\.?json5?/.test(langInfo)
            ? generateJSON
            : generateYAML
          const { code: generatedCode } = generate(code, parseOptions)
          debug('generated code', generatedCode)
          // TODO: error handling & sourcempa
          return Promise.resolve(generatedCode)
        } else {
          return Promise.resolve(code)
        }
      }
    }
  }
}
Example #6
Source File: index.ts    From vanilla-extract with MIT License 4 votes vote down vote up
export function vanillaExtractPlugin({ identifiers }: Options = {}): Plugin {
  let config: ResolvedConfig;
  let server: ViteDevServer;
  let postCssConfig: PostCSSConfigResult | null;
  const cssMap = new Map<string, string>();

  let virtualExt: string;
  let packageName: string;

  return {
    name: 'vanilla-extract',
    enforce: 'pre',
    configureServer(_server) {
      server = _server;
    },
    config(_userConfig, env) {
      const include =
        env.command === 'serve' ? ['@vanilla-extract/css/injectStyles'] : [];

      return {
        optimizeDeps: { include },
        ssr: {
          external: [
            '@vanilla-extract/css',
            '@vanilla-extract/css/fileScope',
            '@vanilla-extract/css/adapter',
          ],
        },
      };
    },
    async configResolved(resolvedConfig) {
      config = resolvedConfig;
      packageName = getPackageInfo(config.root).name;

      if (config.command === 'serve') {
        postCssConfig = await resolvePostcssConfig(config);
      }

      virtualExt = `.vanilla.${config.command === 'serve' ? 'js' : 'css'}`;
    },
    resolveId(id) {
      if (!id.endsWith(virtualExt)) {
        return;
      }

      const normalizedId = id.startsWith('/') ? id.slice(1) : id;

      if (cssMap.has(normalizedId)) {
        return normalizePath(path.join(config.root, normalizedId));
      }
    },
    load(id) {
      if (!id.endsWith(virtualExt)) {
        return;
      }

      const cssFileId = id.slice(config.root.length + 1);
      const css = cssMap.get(cssFileId);

      if (typeof css !== 'string') {
        return;
      }

      if (!server) {
        return css;
      }

      return outdent`
        import { injectStyles } from '@vanilla-extract/css/injectStyles';
        
        const inject = (css) => injectStyles({
          fileScope: ${JSON.stringify({ filePath: cssFileId })},
          css
        });

        inject(${JSON.stringify(css)});

        import.meta.hot.on('${styleUpdateEvent(cssFileId)}', (css) => {
          inject(css);
        });   
      `;
    },
    async transform(code, id, ssrParam) {
      if (!cssFileFilter.test(id)) {
        return null;
      }

      let ssr: boolean | undefined;

      if (typeof ssrParam === 'boolean') {
        ssr = ssrParam;
      } else {
        ssr = ssrParam?.ssr;
      }

      const index = id.indexOf('?');
      const validId = index === -1 ? id : id.substring(0, index);

      if (ssr) {
        return addFileScope({
          source: code,
          filePath: normalizePath(validId),
          rootPath: config.root,
          packageName,
        });
      }

      const { source, watchFiles } = await compile({
        filePath: validId,
        cwd: config.root,
      });

      for (const file of watchFiles) {
        // In start mode, we need to prevent the file from rewatching itself.
        // If it's a `build --watch`, it needs to watch everything.
        if (config.command === 'build' || file !== id) {
          this.addWatchFile(file);
        }
      }

      const output = await processVanillaFile({
        source,
        filePath: validId,
        identOption:
          identifiers ?? (config.mode === 'production' ? 'short' : 'debug'),
        serializeVirtualCssPath: async ({ fileScope, source }) => {
          const id = `${fileScope.filePath}${virtualExt}`;

          let cssSource = source;

          if (postCssConfig) {
            const postCssResult = await (await import('postcss'))
              .default(postCssConfig.plugins)
              .process(source, {
                ...postCssConfig.options,
                from: undefined,
                map: false,
              });

            cssSource = postCssResult.css;
          }

          if (server && cssMap.has(id) && cssMap.get(id) !== source) {
            const { moduleGraph } = server;
            const moduleId = normalizePath(path.join(config.root, id));
            const module = moduleGraph.getModuleById(moduleId);

            if (module) {
              moduleGraph.invalidateModule(module);
            }

            server.ws.send({
              type: 'custom',
              event: styleUpdateEvent(id),
              data: cssSource,
            });
          }

          cssMap.set(id, cssSource);

          return `import "${id}";`;
        },
      });

      return {
        code: output,
        map: { mappings: '' },
      };
    },
  };
}