All files / src/plugins MarkdownViewer.vue.js

66.66% Statements 8/12
80% Branches 4/5
71.42% Functions 5/7
66.66% Lines 8/12

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88                                1x       1x                   5x   5x                                                                         9x   9x 9x                 5x            
// @ts-check
import MarkdownIt from "markdown-it";
// @ts-ignore
import { full as MarkdownItEmoji } from "markdown-it-emoji";
import MarkdownItTasklists from "markdown-it-task-lists";
import MarkdownItLinkAttributes from "markdown-it-link-attributes";
 
import { assign, set } from "lodash";
import Vue from "vue";
 
/**
 * @typedef {{
 *  mdContainer: HTMLDivElement
 * }} Refs
 */
 
const component = /** @type {V.Constructor<any, Refs>} */ (Vue).extend({
  name: "MarkdownViewer",
  props: {
    value: { type: [ String ], default: "" },
    options: { type: Object, default: () => ({}) }
  },
  /**
   * @return {{
    *   mdOptions: MarkdownIt.Options,
    *   mdinstance: MarkdownIt
    * }}
    */
  data() {
    /** @type MarkdownIt.Options */
    const mdOptions = assign({}, { linkify: true },
      /** @type MarkdownIt.Options */(this.options));
    return {
      mdOptions,
      mdinstance: new MarkdownIt(mdOptions)
      .use(MarkdownItEmoji)
      .use(MarkdownItTasklists, {
        enabled: true,
        label: true,
        labelAfter: true
      })
      .use(MarkdownItLinkAttributes, {
        attrs: {
          target: "_blank",
          rel: "noopener"
        }
      })
    };
  },
  watch: {
    options: {
      deep: true,
      /**
       * @param {any} options
       */
      handler(options) {
        // eslint-disable-next-line guard-for-in
        for (const key in options) {
          set(this.mdOptions, key, options[key]);
        }
        this.mdinstance.set(this.mdOptions);
      }
    },
    value: {
      immediate: true,
      /**
       * @param {string} val
       */
      handler(val) {
        this.$nextTick(() => {
          // this is async, do ensure that things haven't been destroyed
          Eif (this.$refs && this.$refs.mdContainer && this.mdinstance) {
            this.$refs.mdContainer.innerHTML = this.mdinstance.render(val);
          }
        });
      }
    }
  },
  mounted() {
    // Beautify output of tables with bootstrap classes
    // eslint-disable-next-line camelcase
    this.mdinstance.renderer.rules.table_open = function() {
      return '<table class="table table-striped">\n';
    };
  }
});
export default component;