markdown-it能够将markdown语法的内容转换为html内容,这样我们使用markdown语法写的笔记,就可以转换作为网页使用了
Markdown语法图文全面详解(10分钟学会)
npm install markdown-it --save
可以看到,使用markdown-it,我们把markdown语法的内容转为了html内容。我们发现,md内容中标记的java语言代码会包裹再pre code标签中,并且再highlight函数中回调。。
转化的html文档
<style lang="scss">
.container {
width: 600px;
margin: 10px auto;
textarea {
outline: none;
}
}
style>
<template>
<div class="container">
<textarea v-model="mdContent" rows="6" style="width: 100%;">textarea>
<div v-html="htmlContent">div>
div>
template>
<script>
import MarkdownIt from 'markdown-it'
const MarkdownIt2 = require('markdown-it')
let md1 = new MarkdownIt()
let md2 = new MarkdownIt2()
console.log(md1);
console.log(md2);
console.log(md1.render('# markdown-it rulezz!'));/* h1>markdown-it rulezz! */
console.log(md2.render('# markdown-it rulezz!'));/* h1>markdown-it rulezz! */
const md = new MarkdownIt({
html: true,
linkify: true,
typographer: true,
breaks: true,
highlight: function(str, lang) {
console.log('str->',str,'lang->',lang);
}
})
export default {
name: 'md2Html',
data() {
return {
mdContent:'',
htmlContent:'',
}
},
watch: {
mdContent(newVal,oldVal) {
this.htmlContent = md.render(newVal)
}
}
}
script>
根据我们前面学到的highlight.js的用法,我们可以这么做,在编辑的时候实时高亮,就是在md转完html,并且渲染完成后,在$nextTick中,高亮对应的html就可以了。
<style lang="scss">
.container {
width: 600px;
margin: 10px auto;
textarea {
outline: none;
}
}
style>
<template>
<div class="container">
<textarea v-model="mdContent" rows="6" style="width: 100%;">textarea>
<div v-html="htmlContent">div>
div>
template>
<script>
import MarkdownIt from 'markdown-it'
const MarkdownIt2 = require('markdown-it')
import hljs from 'highlight.js'
import 'highlight.js/styles/atom-one-dark.css'
let md1 = new MarkdownIt()
let md2 = new MarkdownIt2()
console.log(md1);
console.log(md2);
console.log(md1.render('# markdown-it rulezz!'));/* h1>markdown-it rulezz! */
console.log(md2.render('# markdown-it rulezz!'));/* h1>markdown-it rulezz! */
const md = new MarkdownIt({
html: true,
linkify: true,
typographer: true,
breaks: true,
highlight: function(str, lang) {
console.log('str->',str,'lang->',lang);
}
})
export default {
name: 'md2Html',
data() {
return {
mdContent:'',
htmlContent:'',
}
},
watch: {
mdContent(newVal,oldVal) {
this.htmlContent = md.render(newVal)
this.$nextTick(()=>{
console.log(333);
document.querySelectorAll('pre code').forEach((el) => {
hljs.highlightElement(el);
});
})
}
}
}
script>
添加功能:
<style lang="scss">
@import url('https://fonts.font.im/css?family=Roboto');
* {
font-family: 'Roboto';
}
.container {
width: 600px;
margin: 10px auto;
textarea {
outline: none;
}
}
/* 行号样式 */
.line-numbers-rows {
position: absolute;
pointer-events: none;
top: 18px;
font-size: 100%;
left: 0.5em;
width: 2.1em;
letter-spacing: -1px;
border-right: 1px solid #0e0f12;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
background-color: #282c34;
}
pre {
position: relative;
padding-left: 2.6em;
line-height: 1.3em;
}
.line-numbers-rows>span {
display: block;
counter-increment: linenumber;
}
pre {
background-color: #282c34;
border-radius: 8px;
}
pre code {
border-radius: 8px;
}
.line-numbers-rows>span:before {
content: counter(linenumber);
color: #999;
display: block;
padding-right: 0.8em;
text-align: right;
}
.language-name {
position: absolute;
top: 9px;
color: #999999;
right: 43px;
font-size: 0.8em;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.copy-btn {
position: absolute;
right: 8px;
top: 8px;
background-color: #525252;
border: none;
padding: 3px 6px;
border-radius: 3px;
color: #cccccc;
cursor: pointer;
display: none;
}
pre:hover .copy-btn {
display: block;
}
.copy-textarea {
position: absolute;
left: -9999px;
top: -9999px;
}
style>
<template>
<div class="container">
<textarea v-model="mdContent" rows="6" style="width: 100%;">textarea>
<div v-html="htmlContent">div>
div>
template>
<script>
import { getArticle } from '@/api/articleApi'
import ClipboardJS from 'clipboard'
console.log(ClipboardJS);
import MarkdownIt from 'markdown-it'
const MarkdownIt2 = require('markdown-it')
import hljs from 'highlight.js'
import 'highlight.js/styles/atom-one-dark.css'
let md1 = new MarkdownIt()
let md2 = new MarkdownIt2()
console.log(md1);
console.log(md2);
console.log(md1.render('# markdown-it rulezz!'));/* h1>markdown-it rulezz! */
console.log(md2.render('# markdown-it rulezz!'));/* h1>markdown-it rulezz! */
const md = new MarkdownIt({
html: true,
linkify: true,
typographer: true,
breaks: true,
highlight: function (str, lang) {
/*
str-> @Configuration
@EnableWebMvc
@EnableGlobalMethodSecurity(prePostEnabled = true) // 因为要控制controller中的方法访问,所以此注解要加到子容器中
@ComponentScan(basePackages = "com.zzhua.controller",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = Service.class)})
public class MyWebConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
// 开启静态资源访问
configurer.enable();
}
}
lang-> java {name: 'Java', aliases: Array(1), keywords: {…}, illegal: /<\/|#/, contains: Array(23), …}
*/
console.log('str->', str, 'lang->', lang, hljs.getLanguage('java'));
/*
@Configuration
@EnableWebMvc
@EnableGlobalMethodSecurity(prePostEnabled = true) // 因为要控制controller中的方法访问,所以此注解要加到子容器中
@ComponentScan(basePackages = "com.zzhua.controller",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = Service.class)})
public class MyWebConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
// 开启静态资源访问
configurer.enable();
}
}
*/
console.log(hljs.highlight(str, { language: lang }).value);
if (lang && hljs.getLanguage(lang)) {
try {
let highlightedHtml = hljs.highlight(str, { language: lang }).value
// 生成行号
let lineNum = highlightedHtml.split('\n').length - 1
let lineNumbersRowsStart = ``
let lineNumbersRowsEnd = ``
for (let i = 0; i < lineNum; i++) {
lineNumbersRowsStart += ``
}
const lineNumbersRows = lineNumbersRowsStart + lineNumbersRowsEnd
let languageName = `${lang}`
// 当前时间加随机数生成唯一的id标识
var d = new Date().getTime();
if (window.performance && typeof window.performance.now === "function") {
d += performance.now();
}
const codeIndex = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
/[xy]/g,
function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);
}
);
// 复制功能需要一个textarea(这个id需要前面加个字母啥的,不能以数字开头)
let textAreaHtml = `">${str}`
let copyButton = `" type="button">`
/* 如果返回的不含pre code标签,它会自己加上;如果返回的含有pre code标签,它就不加了 */
return `${lang}
hljs">${highlightedHtml}
${lineNumbersRows}${languageName}${copyButton}${textAreaHtml}
`;
} catch (__) { }
}
return ""
}
})
export default {
name: 'md2Html',
data() {
return {
mdContent: '',
htmlContent: '',
}
},
mounted() {
getArticle(29).then(data => {
this.mdContent = data.mdContent
})
},
watch: {
mdContent(newVal, oldVal) {
let _this = this
this.htmlContent = md.render(newVal)
this.$nextTick(() => {
var clipboard = new ClipboardJS('.copy-btn');
clipboard.on('success', function (e) {
console.info('Action:', e.action);
console.info('Text:', e.text);
console.info('Trigger:', e.trigger);
_this.$toast('success','复制成功了哦');
e.clearSelection();
});
clipboard.on('error', function (e) {
console.error('Action:', e.action);
console.error('Trigger:', e.trigger);
});
})
}
}
}
script>
有些markdown语法,在没有装插件之前不能正常显示,需要安装插件后,才能正确显示。
需要安装插件,安装命令在后面
import MarkdownIt from 'markdown-it'
let md1 = new MarkdownIt()
console.log('未用markdown-it-sub时: ', md1.render('H~2~0')); /* 未用markdown-it-sub时: H~2~0
*/
const md3 = new MarkdownIt().use(require('markdown-it-sub'))
console.log('使用markdown-it-sub时: ', md3.render('H~2~0')); /* 使用markdown-it-sub时: H20
*/
console.log(md3.render('Hello from mars :satellite:'));
md3.use(require('markdown-it-emoji')) /* Hello from mars :satellite:
*/
console.log(md3.render('Hello from mars :satellite:'));/* Hello from mars
*/
npm i markdown-it-sub markdown-it-sup markdown-it-mark markdown-it-abbr markdown-it-container markdown-it-deflist markdown-it-emoji markdown-it-footnote markdown-it-ins markdown-it-katex-external markdown-it-task-lists --save
<style lang="scss">
@import url('https://fonts.font.im/css?family=Roboto');
* {
font-family: 'Roboto';
}
.container {
width: 600px;
margin: 10px auto;
textarea {
outline: none;
}
}
/* 行号样式 */
.line-numbers-rows {
position: absolute;
pointer-events: none;
top: 18px;
font-size: 100%;
left: 0.5em;
width: 2.1em;
letter-spacing: -1px;
border-right: 1px solid #0e0f12;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
background-color: #282c34;
}
pre {
position: relative;
padding-left: 2.6em;
line-height: 1.3em;
}
.line-numbers-rows>span {
display: block;
counter-increment: linenumber;
}
pre {
background-color: #282c34;
border-radius: 8px;
}
pre code {
border-radius: 8px;
}
.line-numbers-rows>span:before {
content: counter(linenumber);
color: #999;
display: block;
padding-right: 0.8em;
text-align: right;
}
.language-name {
position: absolute;
top: 9px;
color: #999999;
right: 43px;
font-size: 0.8em;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.copy-btn {
position: absolute;
right: 8px;
top: 8px;
background-color: #525252;
border: none;
padding: 3px 6px;
border-radius: 3px;
color: #cccccc;
cursor: pointer;
display: none;
}
pre:hover .copy-btn {
display: block;
}
.copy-textarea {
position: absolute;
left: -9999px;
top: -9999px;
}
style>
<template>
<div class="container">
<textarea v-model="mdContent" rows="6" style="width: 100%;">textarea>
<div v-html="htmlContent">div>
div>
template>
<script>
import { getArticle } from '@/api/articleApi'
import ClipboardJS from 'clipboard'
console.log(ClipboardJS);
import MarkdownIt from 'markdown-it'
const MarkdownIt2 = require('markdown-it')
import hljs from 'highlight.js'
import 'highlight.js/styles/atom-one-dark.css'
let md1 = new MarkdownIt()
let md2 = new MarkdownIt2()
console.log(md1);
console.log(md2);
console.log(md1.render('# markdown-it rulezz!'));/* h1>markdown-it rulezz! */
console.log(md2.render('# markdown-it rulezz!'));/* h1>markdown-it rulezz! */
const md = new MarkdownIt({
html: true,
linkify: true,
typographer: true,
breaks: true,
highlight: function (str, lang) {
/*
str-> @Configuration
@EnableWebMvc
@EnableGlobalMethodSecurity(prePostEnabled = true) // 因为要控制controller中的方法访问,所以此注解要加到子容器中
@ComponentScan(basePackages = "com.zzhua.controller",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = Service.class)})
public class MyWebConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
// 开启静态资源访问
configurer.enable();
}
}
lang-> java {name: 'Java', aliases: Array(1), keywords: {…}, illegal: /<\/|#/, contains: Array(23), …}
*/
console.log('str->', str, 'lang->', lang, hljs.getLanguage('java'));
/*
@Configuration
@EnableWebMvc
@EnableGlobalMethodSecurity(prePostEnabled = true) // 因为要控制controller中的方法访问,所以此注解要加到子容器中
@ComponentScan(basePackages = "com.zzhua.controller",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = Service.class)})
public class MyWebConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
// 开启静态资源访问
configurer.enable();
}
}
*/
console.log(hljs.highlight(str, { language: lang }).value);
if (lang && hljs.getLanguage(lang)) {
try {
let highlightedHtml = hljs.highlight(str, { language: lang }).value
// 生成行号
let lineNum = highlightedHtml.split('\n').length - 1
let lineNumbersRowsStart = ``
let lineNumbersRowsEnd = ``
for (let i = 0; i < lineNum; i++) {
lineNumbersRowsStart += ``
}
const lineNumbersRows = lineNumbersRowsStart + lineNumbersRowsEnd
let languageName = `${lang}`
// 当前时间加随机数生成唯一的id标识
var d = new Date().getTime();
if (window.performance && typeof window.performance.now === "function") {
d += performance.now();
}
const codeIndex = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
/[xy]/g,
function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);
}
);
// 复制功能需要一个textarea(这个id需要前面加个字母啥的,不能以数字开头)
let textAreaHtml = `">${str}`
let copyButton = `" type="button">`
/* 如果返回的不含pre code标签,它会自己加上;如果返回的含有pre code标签,它就不加了 */
return `${lang}
hljs">${highlightedHtml}
${lineNumbersRows}${languageName}${copyButton}${textAreaHtml}
`;
} catch (__) { }
}
return ""
}
}) .use(require("markdown-it-sub"))
.use(require("markdown-it-sup"))
.use(require("markdown-it-mark"))
.use(require("markdown-it-abbr"))
.use(require("markdown-it-container"))
.use(require("markdown-it-deflist"))
.use(require("markdown-it-emoji"))
.use(require("markdown-it-footnote"))
.use(require("markdown-it-ins"))
.use(require("markdown-it-katex-external"))
.use(require("markdown-it-task-lists"));
console.log('未用markdown-it-sub时: ', md1.render('H~2~0')); /* 未用markdown-it-sub时: H~2~0
*/ const md3 = new MarkdownIt() .use(require('markdown-it-sub')) console.log('使用markdown-it-sub时: ', md3.render('H~2~0')); /* 使用markdown-it-sub时:H20
*/ console.log(md3.render('Hello from mars :satellite:')); md3.use(require('markdown-it-emoji')) /*Hello from mars :satellite:
*/ console.log(md3.render('Hello from mars :satellite:'));/*Hello from mars
*/ export default { name: 'md2Html', data() { return { mdContent: '', htmlContent: '', } }, mounted() { getArticle(29).then(data => { this.mdContent = data.mdContent }) }, watch: { mdContent(newVal, oldVal) { let _this = this this.htmlContent = md.render(newVal) this.$nextTick(() => { var clipboard = new ClipboardJS('.copy-btn'); clipboard.on('success', function (e) { console.info('Action:', e.action); console.info('Text:', e.text); console.info('Trigger:', e.trigger); _this.$toast('success','复制成功了哦'); e.clearSelection(); }); clipboard.on('error', function (e) { console.error('Action:', e.action); console.error('Trigger:', e.trigger); }); }) } } } script>