Skip to main content

Markdown

WdMarkdown

Applicable Scenarios

The markdown display component implemented based on markdown-it.

Basic Capabilities Description

  1. Supports markdown syntax
  2. Initialization with presets and options, passing preset options via the options parameter.
({
html: html: false, // Enable HTML tags in the source code
xhtmlOut: xhtmlOut: false, // Use / to close single tags (e.g., <br />).
// This option is only compatible with the full CommonMark mode.
breaks: breaks: false, // Convert line breaks in paragraphs to <br> tags.
langPrefix: langPrefix: 'language-', // The CSS language prefix for fenced code blocks. Useful for additional code highlighting.
linkify: linkify: false, // Automatically convert URL-like text to links.

// Enable some language-neutral replacements + quote beautification
typographer: false,

// Double + single quotes replacement pairs, when typographer is enabled.
// Or smart quotes, etc., which can be a String or Array.
//
// For example, you can support '«»„"' for Russians, '„"‚‘' for Germans.
quotes: '""‘’',
});

Extended Scenarios Description

1. How to Use Mermaid in Markdown

Mermaid is a JavaScript-based open-source library that enables users to quickly generate various diagrams—including flowcharts, sequence diagrams, Gantt charts, and mind maps—through concise text and code syntax.

    1. Load Mermaid
Image a4f5b9e7a1c16f16aacfacfac89f8723
<script src="https://cdn.jsdelivr.net/npm/mermaid@10.9.1/dist/mermaid.min.js"></script>

Domestic cdn address:

<script src="https://cdn.staticfile.net/mermaid/10.7.0/mermaid.min.js"></script>
Note
  • Currently, loading external resources is only supported on the Web side and not yet available for mini-programs.
  • In some cases, the CDN of jsdeliver on which hosted scripts depend cannot be accessed domestically, resulting in the scripts not being properly enabled. Consider using other CDNs.
    1. Create the method mermaidRun
export default function ({ event, data }) {
setTimeout(() => {
mermaid.run({
querySelector: '.language-mermaid',
});
}, 0);
}
    1. Call the mermaidRun method in the markdownReady event to render the diagram
    1. Write markdown

```mermaid graph TD A[Christmas] -->|Get money| B(Go shopping) B --> C{Let me think} C -->|One| D[Laptop] C -->|Two| E[iPhone] C -->|Three| F[Car] ```

Image bcef35042620cdbfb9d8ec389a6c12c5

How to use katex in Markdown

katex is a fast, easy-to-use JavaScript library for TeX math rendering on the Web. katex rendering can be supported by loading the katex plugin.

    1. Load katex
Image a4f5b9e7a1c16f16aacfacfac89f8723
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">
<!-- The loading of KaTeX is deferred to speed up page rendering -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" integrity="sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg" crossorigin="anonymous"></script>
Note
  • Currently, loading external resources is only supported on the Web side and not yet available for mini-programs.
  • In some cases, the CDN of jsdeliver on which hosted scripts depend cannot be accessed domestically, resulting in the scripts not being properly enabled.
    1. Create the katex plugin method
var katex = window.katex;

// Test if potential opening or closing delimieter
// Assumes that there is a "$" at state.src[pos]
function isValidDelim(state, pos) {
var prevChar,
nextChar,
max = state.posMax,
can_open = true,
can_close = true;

prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1;
nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1;

// Check non-whitespace conditions for opening and closing, and
// check that closing delimeter isn't followed by a number
if (
prevChar === 0x20 /* " " */ ||
prevChar === 0x09 /* \t */ ||
(nextChar >= 0x30 /* "0" */ && nextChar <= 0x39) /* "9" */
) {
can_close = false;
}
if (nextChar === 0x20 /* " " */ || nextChar === 0x09 /* \t */) {
can_open = false;
}

return {
can_open: can_open,
can_close: can_close,
};
}

function math_inline(state, silent) {
var start, match, token, res, pos, esc_count;

if (state.src[state.pos] !== '$') {
return false;
}

res = isValidDelim(state, state.pos);
if (!res.can_open) {
if (!silent) {
state.pending += '$';
}
state.pos += 1;
return true;
}

// First check for and bypass all properly escaped delimieters
// This loop will assume that the first leading backtick can not
// be the first character in state.src, which is known since
// we have found an opening delimieter already.
start = state.pos + 1;
match = start;
while ((match = state.src.indexOf('$', match)) !== -1) {
// Found potential $, look for escapes, pos will point to
// first non escape when complete
pos = match - 1;
while (state.src[pos] === '\\') {
pos -= 1;
}

// Even number of escapes, potential closing delimiter found
if ((match - pos) % 2 == 1) {
break;
}
match += 1;
}

// No closing delimter found. Consume $ and continue.
if (match === -1) {
if (!silent) {
state.pending += '$';
}
state.pos = start;
return true;
}

// Check if we have empty content, ie: $$. Do not parse.
if (match - start === 0) {
if (!silent) {
state.pending += '$$';
}
state.pos = start + 1;
return true;
}

// Check for valid closing delimiter
res = isValidDelim(state, match);
if (!res.can_close) {
if (!silent) {
state.pending += '$';
}
state.pos = start;
return true;
}

if (!silent) {
token = state.push('math_inline', 'math', 0);
token.markup = '$';
token.content = state.src.slice(start, match);
}

state.pos = match + 1;
return true;
}

function math_block(state, start, end, silent) {
var firstLine,
lastLine,
next,
lastPos,
found = false,
token,
pos = state.bMarks[start] + state.tShift[start],
max = state.eMarks[start];

if (pos + 2 > max) {
return false;
}
if (state.src.slice(pos, pos + 2) !== '$$') {
return false;
}

pos += 2;
firstLine = state.src.slice(pos, max);

if (silent) {
return true;
}
if (firstLine.trim().slice(-2) === '$$') {
// Single line expression
firstLine = firstLine.trim().slice(0, -2);
found = true;
}

for (next = start; !found; ) {
next++;

if (next >= end) {
break;
}

pos = state.bMarks[next] + state.tShift[next];
max = state.eMarks[next];

if (pos < max && state.tShift[next] < state.blkIndent) {
// non-empty line with negative indent should stop the list:
break;
}

if (state.src.slice(pos, max).trim().slice(-2) === '$$') {
lastPos = state.src.slice(0, max).lastIndexOf('$$');
lastLine = state.src.slice(pos, lastPos);
found = true;
}
}

state.line = next + 1;

token = state.push('math_block', 'math', 0);
token.block = true;
token.content =
(firstLine && firstLine.trim() ? firstLine + '\n' : '') +
state.getLines(start + 1, next, state.tShift[start], true) +
(lastLine && lastLine.trim() ? lastLine : '');
token.map = [start, state.line];
token.markup = '$$';
return true;
}

export default function math_plugin(md, options) {
// Default options

options = options || {};

// set KaTeX as the renderer for markdown-it-simplemath
var katexInline = function (latex) {
options.displayMode = false;
try {
return katex.renderToString(latex, options);
} catch (error) {
if (options.throwOnError) {
console.log(error);
}
return latex;
}
};

var inlineRenderer = function (tokens, idx) {
return katexInline(tokens[idx].content);
};

var katexBlock = function (latex) {
options.displayMode = true;
try {
return '<p>' + katex.renderToString(latex, options) + '</p>';
} catch (error) {
if (options.throwOnError) {
console.log(error);
}
return latex;
}
};

var blockRenderer = function (tokens, idx) {
return katexBlock(tokens[idx].content) + '\n';
};

md.inline.ruler.after('escape', 'math_inline', math_inline);
md.block.ruler.after('blockquote', 'math_block', math_block, {
alt: ['paragraph', 'reference', 'blockquote', 'list'],
});
md.renderer.rules.math_inline = inlineRenderer;
md.renderer.rules.math_block = blockRenderer;
}
    1. Use the plugin to call the method for updating the markdown instance in the markdownReady event
$w.markdown2.markdownInstance?.use($w.page.handler.katex);
    1. Write markdown

# Maxwell's Equations


equation | description
----------|------------
$\nabla \cdot \vec{\mathbf{B}} = 0$ | divergence of $\vec{\mathbf{B}}$ is zero
$\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | curl of $\vec{\mathbf{E}}$ is proportional to the rate of change of $\vec{\mathbf{B}}$
$\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _wha?_
Image 92a7b9c050b93ec05016a5c117b67b1d

Property Introduction

External properties received by the component

Property Name
Property Identifier
Type
Description
Contentvaluestring

markdown display content

Example: "---\n__Advertisement :)__\n\n- __[pica](https://nodeca.github.io/pica/demo/)__ - high quality and fast image\n resize in browser.\n- __[babelfish](https://github.com/nodeca/babelfish/)__ - developer friendly\n i18n with plurals support and easy syntax.\n\nYou will like those projects!\n\n---\n\n# h1 Heading 8-)\n## h2 Heading\n### h3 Heading\n#### h4 Heading\n##### h5 Heading\n###### h6 Heading\n\n\n## Horizontal Rules\n\n___\n\n---\n\n***\n\n\n## Typographic replacements\n\nEnable typographer option to see result.\n\n(c) (C) (r) (R) (tm) (TM) (p) (P) +-\n\ntest.. test... test..... test?..... test!....\n\n!!!!!! ???? ,, -- ---\n\n\"Smartypants, double quotes\" and 'single quotes'\n\n\n## Emphasis\n\n**This is bold text**\n\n__This is bold text__\n\n*This is italic text*\n\n_This is italic text_\n\n~~Strikethrough~~\n\n\n## Blockquotes\n\n\n> Blockquotes can also be nested...\n>> ...by using additional greater-than signs right next to each other...\n> > > ...or with spaces between arrows.\n\n\n## Lists\n\nUnordered\n\n+ Create a list by starting a line with `+`, `-`, or `*`\n+ Sub-lists are made by indenting 2 spaces:\n - Marker character change forces new list start:\n * Ac tristique libero volutpat at\n + Facilisis in pretium nisl aliquet\n - Nulla volutpat aliquam velit\n+ Very easy!\n\nOrdered\n\n1. Lorem ipsum dolor sit amet\n2. Consectetur adipiscing elit\n3. Integer molestie lorem at massa\n\n\n1. You can use sequential numbers...\n1. ...or keep all the numbers as `1.`\n\nStart numbering with offset:\n\n57. foo\n1. bar\n\n\n## Code\n\nInline `code`\n\nIndented code\n\n // Some comments\n line 1 of code\n line 2 of code\n line 3 of code\n\n\nBlock code \"fences\"\n\n```\nSample text here...\n```\n\nSyntax highlighting\n\n``` js\nvar foo = function (bar) {\n return bar++;\n};\n\nconsole.log(foo(5));\n```\n\n## Tables\n\n| Option | Description |\n| ------ | ----------- |\n| data | path to data files to supply the data that will be passed into templates. |\n| engine | engine to be used for processing templates. Handlebars is the default. |\n| ext | extension to be used for dest files. |\n\nRight aligned columns\n\n| Option | Description |\n| ------:| -----------:|\n| data | path to data files to supply the data that will be passed into templates. |\n| engine | engine to be used for processing templates. Handlebars is the default. |\n| ext | extension to be used for dest files. |\n\n\n## Links\n\n[link text](http://dev.nodeca.com)\n\n[link with title](http://nodeca.github.io/pica/demo/ \"title text!\")\n\nAutoconverted link https://github.com/nodeca/pica (enable linkify to see)\n\n\n## Images\n\n![image](https://octodex.github.com/images/minion.png)\n"

Optionoptionsobject

SDK initialization configuration

Events

Events exposed by the component. You can listen to component events to trigger external actions

Event Name
Event Code
Event Output Parameters event.detail
Applicable Scenarios
Description
markdown ReadyonReadyobject
  • markdownInstance: object markdown实例
    Compatible with all platforms

    The current markdown has completed instance initialization. You can call the markdown instance method.

    Properties API

    Through the Property API, you can access the internal state and property values of components. You can access internal values using$w.componentId.propertyName, such as $w.input1.value. For details, please refer to Property API

    Read-only Property Name
    Property Identifier
    Type
    Description
    Contentvaluestring

    markdown display content

    markdown instancemarkdownInstanceobject

    可以通过markdown实例调用markdown实例方法,如:markdownInstance.render("# markdown-it rulezz!")具体内容见markdown-it官方文档

    Method API

    Through the Method API, you can programmatically trigger internal methods of components, such as submitting forms, displaying popups, etc. You can call component methods using $w.componentId.methodName, such as $w.form1.submit()

    Method Name
    Method Identifier
    Parameters
    Method Description
    Refresh a markdown instanceupdateMarkdownInstanceobject
    • markdownInstance: object markdown实例

      可以通过markdown实例调用markdown实例方法,如:markdownInstance.render("# markdown-it rulezz!")具体内容见markdown-it官方文档

      Refresh a markdown instance

      Style API

      Through the Style API, you can override the styles of internal elements in components to achieve customization. For example, in the low-code editor, you can write styles for all button components using #wd-page-root .wd-btn, and control individual component styles with :scope. For detailed instructions, please refer toStyle API

      Name
      Class Name
      Description and Examples
      root element.wd-markdownlink component root element
      /* :scope refers to the current component element */
      /* For details, refer to the Style API documentation */
      :scope.wd-markdown {
        /* Write CSS styles here */
      }
      PC-side root element link.wd-pc-markdownWrite styles for PC URLs
      /* :scope refers to the current component element */
      /* For details, refer to the Style API documentation */
      :scope.wd-pc-markdown {
        /* Write CSS styles here */
      }
      H5 root element link.wd-h5-markdownWrite style for H5 URLs
      /* :scope refers to the current component element */
      /* For details, refer to the Style API documentation */
      :scope.wd-h5-markdown {
        /* Write CSS styles here */
      }
      Mini program link root element.wd-mp-markdownCan write styles for URLs in the mini program
      /* :scope refers to the current component element */
      /* For details, refer to the Style API documentation */
      :scope.wd-mp-markdown {
        /* Write CSS styles here */
      }

      Learn about Style API

      Limits Description

      The markdown display in Mini Programs is achieved by parsing markdown into html using markdown-it, and then rendering it via the Mini Program's rich-text component. Therefore, the markdown rendering capability in Mini Programs is limited, with some styling details differing slightly from the web version. Please refer to the actual runtime effects in the Mini Program for accuracy.

      Frequently Asked Questions

      Why do externally linked images display abnormally?

      Many websites' images verify the page referrer, likely due to enabled hotlink protection. When accessed directly, there's no referrer source, but when used on your page, access may be blocked by referrer verification. You may try alternative image resources or check the loading failure messages in F12 developer tools.