# webpack
**Repository Path**: hjh925678208/webpack
## Basic Information
- **Project Name**: webpack
- **Description**: webpack 工具库
- **Primary Language**: JavaScript
- **License**: ISC
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2022-11-12
- **Last Updated**: 2025-01-29
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# @imhjh/webpack 文档
[源码](https://gitee.com/hjh925678208/webpack)
## 安装
```bash
# npm
npm install @imhjh/webpack --save-dev
# yarn
yarn add @imhjh/webpack --save
```
## 使用
以 `MarkdownLoader` 为例
- webpack.config.js
```js
const { MarkdownLoader } = require("@imhjh/webpack")
module.exports = {
module: {
rules: [{ test: /\.md/, use: [MarkdownLoader] }]
}
}
```
- react 配置
`create-react-app` 创建的项目默认 `webpack.config.js` 是隐藏的,需要使用命令显示,但会造成项目臃肿。
可以使用其他配置,以下以 `@craco/craco` 为例。
```js
// 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` 的配置方式
```js
// 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` 中添加以下配置:
```json
{
"compilerOptions": {
"moduleResolution": "node16",
// 或
"moduleResolution": "nodenext"
}
}
```
## loader
### MarkdownLoader
用于加载 markdown 文件的 loader。代码块高亮默认利用 `prismjs` 进行解析。
插件只会将 markdown 解析为 html 代码,但不会添加样式,需要自行实现。所有样式需要自行实现。
内部使用了以下依赖:
[文档解析 - markdown-it](https://github.com/markdown-it/markdown-it)
[标题锚点 - markdown-it-anchor](https://github.com/valeriangalliat/markdown-it-anchor)
[目录生成 - markdown-it-toc-done-right](https://github.com/nagaozen/markdown-it-toc-done-right)
[自定义容器 - markdown-it-container](https://github.com/markdown-it/markdown-it-container)
[代码高亮解析 - Prismjs](https://prismjs.com/)
- 配置(下面参数显示的是默认配置)
```js
// webpack 中配置
{
/* markdown-it 的初始化配置 */
preset: "default", // markdown-it 的预设模式
html: undefined, // 在源码中启用 HTML 标签
xhtmlOut: undefined, // 使用 "/" 来闭合单标签
breaks: undefined, // 转换段落里的 '\n' 到
。
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 文件的效果
```js
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](https://github.com/mAAdhaTTah/babel-plugin-prismjs)。
```js
import { useMarkdownResolver } from "@imhjh/webpack/utils"
const { resolver, markdownIt, update, TOCCode } = useMarkdownResolver({
/* 支持除 languages 以外的所有 MarkdownLoader 配置 */
})
const html = resolver("# markdown 文本")
```
## types
### MarkdownLoader 相关
```ts
// 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' 到
*/
langPrefix?: string /** markdown-it 配置: 代码块的 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 */
}
```