npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@imhjh/webpack

v4.9.1

Published

webpack 工具库

Readme

@imhjh/webpack 文档

源码

安装

# npm
npm install @imhjh/webpack --save-dev
# yarn
yarn add @imhjh/webpack --save

使用

MarkdownLoader 为例

  • webpack.config.js

    const { MarkdownLoader } = require("@imhjh/webpack")
    
    module.exports = {
      module: {
        rules: [{ test: /\.md/, use: [MarkdownLoader] }]
      }
    }
  • react 配置

    create-react-app 创建的项目默认 webpack.config.js 是隐藏的,需要使用命令显示,但会造成项目臃肿。

    可以使用其他配置,以下以 @craco/craco 为例。

    // craco.config.js
    const { MarkdownLoader } = require("@imhjh/webpack")
    
    module.exports = {
      webpack: {
        configure: (webpackConfig, { env, paths }) => {
          // 需要将 loader 插入到 react-script 内置 webpack.config.js 的 loader 前面。
          const oneOfRule = webpackConfig.module.rules.find((rule) => !!rule.oneOf)
          if (oneOfRule) {
            oneOfRule.oneOf.unshift({ test: /\.md$/, use: [MarkdownLoader] })
          }
          return webpackConfig
        }
      }
    }
  • vue 配置

    vue-cli 的配置方式

    // vue.config.js
    const { MarkdownLoader } = require("@imhjh/webpack")
    
    module.exports = {
      // vue.config.js 内部使用 webpack-chain 配置 webpack
      chainWebpack: (config) => {
        config.module
          .rule("markdown") // webpack-chain 内部用于辨别规则的名称
          .test(/\.md$/)
          .use("markdown") // webpack-chain 内部用于辨别loader的名称
          .loader(MarkdownLoader)
          .options({}) // 相关配置
      }
    }

说明

由于项目通过 package#exports 配置导出。

因此在使用 typescript 时会出现警告,需要在 tsconfig.json 中添加以下配置:

{
  "compilerOptions": {
    "moduleResolution": "node16",
    // 或
    "moduleResolution": "nodenext"
  }
}

loader

MarkdownLoader

用于加载 markdown 文件的 loader。代码块高亮默认利用 prismjs 进行解析。

插件只会将 markdown 解析为 html 代码,但不会添加样式,需要自行实现。所有样式需要自行实现。

内部使用了以下依赖:

文档解析 - markdown-it

标题锚点 - markdown-it-anchor

目录生成 - markdown-it-toc-done-right

自定义容器 - markdown-it-container

代码高亮解析 - Prismjs

  • 配置(下面参数显示的是默认配置)

    // webpack 中配置
    
    {
      /* markdown-it 的初始化配置 */
      preset: "default", // markdown-it 的预设模式
      html: undefined, // 在源码中启用 HTML 标签
      xhtmlOut: undefined, // 使用 "/" 来闭合单标签
      breaks: undefined, // 转换段落里的 '\n' 到 <br>。
      langPrefix: undefined, // pre 代码块的 CSS 语言前缀
      linkify: undefined, // 将类似 URL 的文本自动转换为链接
      typographer: undefined, // 启用一些语言中立的替换 + 引号美化
      quotes: undefined, // 双 + 单引号替换对,当 typographer 启用时
    
      /* 锚点插件 markdown-it-anchor */
      useAnchor: false, // 是否开启插件
      // 使用 markdown-it-anchor 配置
      anchorOptions: {
        slugify: (s) => encodeURIComponent(String(s).trim().toLowerCase().replace(/\s+/g, "-")),
        permalink: MarkdownItAnchor.permalink.linkInsideHeader({
          class: "imhjh-md-anchor",
          placement: "before",
          space: false,
          symbol: "#"
        })
      },
    
      /* 目录插件 markdown-it-toc-done-right */
      useTOC: false, // 是否使用开启插件
      // 使用 markdown-it-toc-done-right 配置
      TOCOptions: {
        slugify: (s) => encodeURIComponent(String(s).trim().toLowerCase().replace(/\s+/g, "-")),
        listType: "ul",
        containerClass: "imhjh-md-toc",
        linkClass: "imhjh-md-toc-anchor"
      },
    
      /* 自定义容器插件 markdown-it-container */
      useContainer: false, // 是否使用开启插件
      // 使用 markdown-it-container 配置
      containerOptions: {
        // 用于配合默认 default render,添加类型
        containerClass: "imhjh-md-container", // 外层容器类名
        titleClass: "imhjh-md-container-title", // 标题容器类名
        bodyClass: "imhjh-md-container-body", // 内容容器类名
        renderMap: {}, // 不同标识的渲染方式
        // 以下为插件自带配置
        marker: ":",
        validate: (params) => true,
        render: (tokens, idx) => {
          /*
            内部进行了二次封装
              1. 解析标题的第一段字符为容器名称
              2. 根据容器名称从 renderMap 中调用渲染函数
              3. 未匹配到的容器名称会调用默认的 default 函数渲染
          */
          /* render 查看 https://gitee.com/hjh925678208/webpack/blob/master/src/dev/utils/markdown.ts#L249 */
          /* default 查看 https://gitee.com/hjh925678208/webpack/blob/master/src/dev/utils/markdown.ts#L135 */
        }
      },
    
      contentClass: "imhjh-md-content", // html 外层 div 的class
      /* prismjs 的语言配置, 完整语言列表 https://prismjs.com/#supported-languages */
      languages: [], // 使用 "all" 表示加载所有语言
      // 解析出未知语言时,映射为其他语言
      languageMap: { default: "js" }, // default:所有未知语言都视作 "js"
    
      // 返回给 markdownIt 前,对高亮解析后的代码块 html 进行二次处理
      codeHandler({ codeHTML, highlightLang, codeSource, sourceLang }) {
        // codeHTML 高亮解析后的代码块 html
        // highlightLang 基于那种语言进行高亮解析
        // codeSource 高亮解析前的代码块 markdown
        // sourceLang 解析 markdown 代码块定义的语言
        return codeHTML
      },
      // 对初始化后的 markdown-it 实例进行处理
      handler(markdownIt, simpleMarkdownIt) {
        // markdownIt:整个解析器的 markdown 实例
        // simpleMarkdownIt:用于在内部对 container 标题等进行解析的 markdown 实例
        // 相较于 markdownIt,simpleMarkdownIt 上没有添加 plugins 等配置
      }
    }
  • 页面导入 markdown 文件的效果

    import MarkdownResult from "module.md"
    
    const { source, html, TOCCode } = MarkdownResult
    
    console.log(source) // 原始的 module.md 文本
    console.log(html) // 解析后的 html
    console.log(TOCCode) // markdown-it-toc-done-right 编译出的目录 html

useMarkdownResolver

MarkdownLoader 内部使用的 markdown 代码解析函数。

用于直接在 browser 环境中使用。

因为 prismjs 的语言模板加载函数只能在 node 环境下使用,所以该函数无法使用 languages 配置。

因此使用 useMarkdownResolver 时若需要加载额外的语言模板,需要配置 babel-plugin-prismjs

import { useMarkdownResolver } from "@imhjh/webpack/utils"

const { resolver, markdownIt, update, TOCCode } = useMarkdownResolver({
  /* 支持除 languages 以外的所有 MarkdownLoader 配置 */
})

const html = resolver("# markdown 文本")

types

MarkdownLoader 相关

// MarkdownLoader 的配置
type MarkdownLoaderOptions = MarkdownResolverOptions & {
  /** prismjs 加载的代码块语言类型:"all" | [langs]。*/
  languages: "all" | string[]
}

// 代码块处理函数入参
interface CodeHandlerParams {
  codeHTML: string /** 高亮解析后的代码块 html */
  highlightLang: string /** 基于那种语言进行高亮解析 */
  codeSource: string /** 高亮解析前的代码块 markdown */
  sourceLang: string /** 解析 markdown 代码块定义的语言 */
}
// 代码块处理函数
interface CodeHandler {
  (params: CodeHandlerParams): string
}
// 容器配置
type ContainerOpts = MarkdownResolverOptions["containerOptions"] & {}
// 容器渲染函数
interface ContainerRender {
  (tokens: any[], idx: number, simpleMarkdownIt, opts: ContainerOpts): string
}
// useMarkdownResolver 配置
interface MarkdownResolverOptions {
  preset?: "default" | "commonmark" | "zero" /** 预设模式 */
  contentClass?: string /** 包裹整个 html 的 div.class */
  languageMap?: { [k: string]: string } /** prismjs无法解析语言的映射:{ 读取的语言: 目标语言 } */
  html?: boolean /** markdown-it 配置:是否在源码中启用 HTML 标签 */
  xhtmlOut?: boolean /** markdown-it 配置:是否使用 "/" 来闭合单标签 */
  breaks?: boolean /** markdown-it 配置:转换段落里的 '\n' 到 <br> */
  langPrefix?: string /** markdown-it 配置:<code /> 代码块的 CSS 类名前缀,默认 imhjh-md- */
  linkify?: boolean /** markdown-it 配置:将类似 URL 的文本自动转换为链接 */
  typographer?: boolean /** markdown-it 配置:启用一些语言中立的替换 + 引号美化 */
  quotes?: string /** markdown-it 配置:双 + 单引号替换对,当 typographer 启用时 */
  codeHandler?: CodeHandler /* 在抛给 markdown-it 之前,对高亮解析后的代码块 html 进行二次处理 */
  handler?: (markdownIt, simpleMarkdownIt) => void /** 使用 markdown 实例作为入参,提供更好的自定义 */

  // 以下配置在 调用 update 时不生效
  useAnchor?: boolean /** 是否使用 markdown-it-anchor 插件 */
  anchorOptions?: object /** markdown-it-anchor 的配置 */
  useTOC?: boolean /** 是否使用 markdown-it-toc-done-right 插件 */
  TOCOptions?: object /** markdown-it-toc-done-right 的配置 */
  useContainer?: boolean /** 是否使用 markdown-it-container 插件  */
  /** markdown-it-container 配置 */
  containerOptions?: {
    containerClass?: string
    titleClass?: string
    bodyClass?: string
    validate?: (params: string) => string
    render?: (tokens: any[], idx: number) => string
    marker?: string
    renderMap?: { [k: string]: ContainerRender }
  }
}
// useMarkdownResolver 返回值
interface MarkdownResolver {
  markdownIt: any /** markdownIt 实例 */
  resolver: (source: string) => { html: string; TOCCode: string } /** 用于处理的 markdown 文本的解析器 */
  update: (opts: MarkdownResolverOptions) => void /** 更新 markdownIt */
}