在 Vuepress
文档中引入图片时,由于某些图片内容密集,必须放大才能看清。虽然可以通过拆分图片解决,但不免有些麻烦。搜索后发现,社区中有两种方案与此相关。其一是 medium-zoom 插件,它虽然支持放大,但默认占满全屏,无法手动调节倍数。另一种是引入 fancybox
,它支持倍数调节,为此有人专门编写了 VSCode 插件,通过快捷键,转换当前 Markdown 文件里的图片标签。这种方式也有缺点,不仅要逐个文件手动转换,而且不符合 Markdown 语法。
由此便确立了目标,通过 Vuepress 的某种机制,自动
将文件里的 Markdown 图片标签转为 fancybox 可识别的 a
标签。
运行时
查阅文档后发现,可以将插件代码注入 Vuepress 生命周期,在浏览器端扫描图片标签并转换。
具体实现如下:首先新建 docs/.vuepress/plugins/fancybox/mixin.js
文件,写入如下代码:
export default {
mounted() {
this.update();
},
updated() {
this.update();
},
methods: {
update() {
document.querySelectorAll("p>img").forEach(img => {
img.parentElement.innerHTML = `<a data-fancybox href="${img.src}" content="${img.alt}">${img.outerHTML}</a>`;
});
}
}
};
随后,在相同文件夹下新建 index.js
文件写入如下代码:
const { path } = require("@vuepress/shared-utils");
module.exports = (options, ctx) => ({
clientRootMixin: path.resolve(__dirname, "mixin.js")
});
最后,在 docs/.vuepress/config.js
中引入 插件
和必要的 js
和 css
文件。
const STATIC_CDN = '//s0.pstatp.com/cdn/expire-1-M/'
module.exports = {
head: [
['script', { src: STATIC_CDN + 'jquery/3.4.0/jquery.min.js' }],
['script', { src: STATIC_CDN + 'fancybox/3.5.7/jquery.fancybox.min.js' }],
['link', { rel: 'stylesheet', href: STATIC_CDN + 'fancybox/3.5.7/jquery.fancybox.min.css' }]
],
plugins: [require('./plugins/fancybox')],
}
编译时
另一种方法是在编译期完成上述步骤,方法是编写 Markdown 插件 改变渲染规则,注入 fancybox 标签。但是由于相对路径的图片会被 Webpack 重新打包,而这发生在 Markdown
渲染之后,造成路径错误。因此必须修改 Webpack
的 vue-loader,让其把 fancybox 标签的 src
属性一并改变。具体编码如下:
首先新建 docs/.vuepress/plugins/fancybox/index.js
文件,写入如下代码:
const PUBLIC_PREFIX = "/docs/.vuepress/public";
module.exports = md => {
md.renderer.rules.image = (tokens, idx) => {
const token = tokens[idx];
const srcIndex = token.attrIndex("src");
const url = token.attrs[srcIndex][1].replace(PUBLIC_PREFIX, "");
const caption = md.utils.escapeHtml(token.content);
return `<a data-fancybox href="${url}" content="${caption}">
<img src="${url}" alt="${caption}" />
</a>`;
};
};
module.exports.webpack = (config, isServer) => {
const inlineLimit = 10000;
config.module
.rule("images")
.test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
.use("url-loader")
.loader("url-loader")
.options({
limit: inlineLimit,
name: `assets/img/[name].[hash:8].[ext]`
});
config.module
.rule("vue")
.uses.store.get("vue-loader")
.store.get("options").transformAssetUrls = {
video: ["src", "poster"],
source: "src",
img: "src",
image: ["xlink:href", "href"],
a: "href"
};
};
随后在 docs/.vuepress/config.js
中引入插件。
const STATIC_CDN = '//s0.pstatp.com/cdn/expire-1-M/'
module.exports = {
head: [
['script', { src: STATIC_CDN + 'jquery/3.4.0/jquery.min.js' }],
['script', { src: STATIC_CDN + 'fancybox/3.5.7/jquery.fancybox.min.js' }],
['link', { rel: 'stylesheet', href: STATIC_CDN + 'fancybox/3.5.7/jquery.fancybox.min.css' }]
],
markdown: {
extendMarkdown: md => md.use(require('./plugin/fancybox'))
},
chainWebpack: require('./plugin/fancybox').webpack
}
使用 Vue 组件
上面两种方法都要手动引入 js
和 css
。如需使用 npm 包,可编写单独的 Vue 组件,直接在 Markdown 中引入。不过那样,VSCode 将无法直接预览。
此外,对于处于 docs/.vuepress/public/
目录中的文件,Webpack
不会重新打包。并且,它是 Vuepress
静态资源的默认根路径,比如 docs/.vuepress/public/1.jpg
在 Markdown
中写成 /1.jpg
才能被 Vuepress
找到。
我们编写文档时,通常都是以 docs
上级作为项目目录,这将导致 VSCode
无法本地预览。通过使用上文提到的第二种方式,我们可以在 Markdown 中编写正常路径,比如 docs/.vuepress/public/1.jpg
,在编译时通过插件将前缀去掉,保证本地预览和编译的正确性。
最后,第二种方式还扩充了相对路径中 Webpack
可识别的 webp
图片格式。即,文档中可引入 md
同级目录下的 webp
图片。具体规则见方式二代码。
如有问题请在下方留言,文章转载请注明出处,详细交流请加下方群组!请大佬不要屏蔽文中广告,因为它将帮我分担服务器开支,如果能帮忙点击我将万分感谢。
markdown-it-remove-image-path-prefix这个是怎么引入的?
忘改了,应该改成 plugins 下创建的文件夹名,文章里是 fancybox
效果有了,图片并没有放大啊,和原来一样大
fancybox 是放大到原始大小,下面的库可以任意缩放,你自己改改https://github.com/fengyuanchen/viewerjs
@(钱币)