vue使用highlight.js 添加行号

2020-04-24  本文已影响0人  醉笙情丶浮生梦

效果图


1587719278(1).jpg

main.js

import hljs from "highlight.js";
import "highlight.js/styles/atom-one-dark.css"; // 样式文件

Vue.directive("highlight", function(el) {
  console.log("自定义指令", el);

  let blocks = el.querySelectorAll("pre code");
  blocks.forEach(block => {
    console.log(block.innerHTML, "block是", block);
    try {
      let str = block.innerHTML;
      let lang = "js";

      // 得到经过highlight.js之后的html代码
      const preCode = hljs.highlight(lang, str, true).value;

      // 以换行进行分割
      // const lines = preCode.split(/\n/).slice(0, -1);
      const linesLength = preCode.split("<br></br>").length;

      // 生成行号 aria-hidden 对浏览器语义化隐藏
      let linesNum = '<span aria-hidden="true" class="line-numbers-rows">';
      for (let index = 0; index < linesLength + 1; index++) {
        linesNum = linesNum + "<span></span>";
      }
      linesNum += "</span>";

      let html = preCode;

      // 右上角语言说明
      // if (linesLength) {
      //     html += '<b class="name">' + lang + "</b>";
      // }

      html =
        '<pre class="hljs"><code>' + html + "</code>" + linesNum + "</pre>";

      block.parentNode.parentNode.innerHTML = html;
    } catch (__) {
      console.log("执行错误", __);
    }

    // 方法一
    // hljs.highlightBlock(block);

    // const linesLength = block.innerHTML.split("<br></br>").length;

    // // 生成行号 aria-hidden 对浏览器语义化隐藏
    // let linesNum = '<span aria-hidden="true" class="line-numbers-rows">';
    // for (let index = 0; index < linesLength + 1; index++) {
    //   linesNum = linesNum + "<span></span>";
    // }
    // linesNum += "</span>";

    // block.parentNode.innerHTML = block.parentNode.innerHTML + linesNum;
  });
});

父组件

<template>
  <div class="page">
    <div>
      <p>{{ code.title }}</p>
      <div v-highlight class="codes">
        <render :render="code.render"> </render>
      </div>
    </div>
  </div>
</template>

<script>
import render from "./render";
export default {
  name: "",
  components: {
    render
  },
  data() {
    // 两种换行都可以
    const br = <br></br>; //{br}
    const n = "\n"; //{n}
    return {
      code: {
        title: "一个标题",
        render: h => {
          return (
            <pre>
              <code>
                var str = "18127446988"
                {n}
                console.log(enStr)
              </code>
            </pre>
          );
        }
      }
    };
  }
};
</script>

<style lang="scss">
.page {
  text-align: center;

  // 方法二
  .codes {
    width: 500px;
    margin: 0 auto;
  }
  .hljs {
    position: relative;
    text-align: left;
    padding: 7px 2px 7px 40px;
    code {
      display: block;
      margin: 0 10px;
    }
  }
  // 方法一
  // .codes {
  //   width: 500px;
  //   margin: 0 auto;
  //   position: relative;
  //   background: #282c34;
  // }
  // pre {
  //   padding-left: 50px;
  // }
  // .hljs {
  //   text-align: left;
  // }

  // 共用
  .line-numbers-rows {
    position: absolute;
    pointer-events: none;
    top: 7px;
    bottom: 7px;
    left: 0;
    font-size: 100%;
    width: 40px;
    text-align: center;
    letter-spacing: -1px;
    border-right: 1px solid rgba(0, 0, 0, 0.66);
    user-select: none;
    counter-reset: linenumber;
    span {
      pointer-events: none;
      display: block;
      counter-increment: linenumber;
      &:before {
        content: counter(linenumber);
        color: #999;
        display: block;
        text-align: center;
      }
    }
  }
}
</style>

子组件

<script>
export default {
  name: "Render",
  functional: true,
  props: {
    render: Function
  },
  render: (h, ctx) => {
    return ctx.props.render ? ctx.props.render(h) : "";
  }
};
</script>

参考:markdown-it代码块渲染、自定义行号
vue使用highlight.js

上一篇 下一篇

猜你喜欢

热点阅读