doocs / md

✍ WeChat Markdown Editor | 一款高度简洁的微信 Markdown 编辑器:支持 Markdown 语法、色盘取色、多图上传、一键下载文档、自定义 CSS 样式、一键重置等特性
https://doocs.github.io/md/
Do What The F*ck You Want To Public License
5.87k stars 947 forks source link

请求增加定理,引理,定义等环境的定义,并渲染 #425

Open Jieli12 opened 1 month ago

Jieli12 commented 1 month ago

首先感谢作者提供如此好用的工具。我在VScode中用Markdown preview enhanced 来渲染markdown文件,这个插件提供了一个自定义的接口,用户可以自己定制环境并设置CSS样式。下面是 parser.js 文件内容:

({
  // Please visit the URL below for more information:
  // https://shd101wyy.github.io/markdown-preview-enhanced/#/extend-parser
  onWillParseMarkdown: async function (markdown) {

    // Define the regex to match the environments and references
    let environments = [
      { name: 'theorem', label: '#theorem:', color: '#ff8618', shape: '♥' },
      { name: 'postulate', label: '#postulate:', color: '#ff8618', shape: '♥' },
      { name: 'axiom', label: '#axiom:', color: '#ff8618', shape: '♥' },
      { name: 'assumption', label: '#assumption:', color: '#ff8618', shape: '♥' },
      { name: 'lemma', label: '#lemma:', color: '#ff8618', shape: '♥' },
      { name: 'corollary', label: '#corollary:', color: '#ff8618', shape: '♥' },
      { name: 'definition', label: '#definition:', color: '#4CAF50', shape: '♣' },
      { name: 'proposition', label: '#proposition:', color: '#00aef7', shape: '♠' }
    ];

    // Construct a regex pattern to match only the labels in the environments array
    let labels = environments.map(env => env.label.slice(1, -1)).join('|');
    let refRegex = new RegExp(`@(${labels}):(\\w*)`, 'g');

    // Store references and their numbers
    let references = {};
    let counts = {};

    environments.forEach(env => {
      counts[env.name] = 0;
    });

    // First pass: Assign numbers to each environment
    environments.forEach(env => {
      let regex = new RegExp(`::: ${env.name}\\s*(\\{${env.label}(.*?)\\})?\\n([\\s\\S]*?)\\n:::\\n`, 'g');
      markdown = markdown.replace(regex, function (match, id, key, body) {
        counts[env.name]++;
        let number = `${env.name.charAt(0).toUpperCase() + env.name.slice(1)} ${counts[env.name]}`;
        if (key) {
          references[`@${env.label.slice(1)}${key}`] = number;
        }
        return match.replace(new RegExp(`::: ${env.name}\\s*(\\{${env.label}(.*?)\\})?`), `::: ${number}`);
      });
    });

    markdown = markdown.replace(refRegex, function (match, id, key) {
      let reference = references[`@${id}:${key}`] || match;
      return `<span style="color: #3c71b7;">${reference}</span>`;
    });

    // Replace each environment with the appropriate HTML structure
    environments.forEach(env => {
      let regex = new RegExp(`::: ${env.name.charAt(0).toUpperCase() + env.name.slice(1)}\\s*(\\d+)\\n([\\s\\S]*?)\\n:::\\n`, 'g');
      markdown = markdown.replace(regex, function (match, key, body) {
        // Trim the body to remove any leading/trailing whitespace
        body = body.trim();
        let idd = `${env.name.charAt(0).toUpperCase() + env.name.slice(1)} ${key}`;
        // Function to find the key by value in the references object
        function getKeyByValue(object, value) {
          return Object.keys(object).find(key => object[key] === value);
        }

        // Find the key that matches the value 'Lemma 1'
        let key1 = getKeyByValue(references, idd);

        // Construct id_initial using the found key
        let id_initial = `${key1.slice(1)}`;

        // Return the HTML structure
        return "<div style=\"position: relative; border: 2px solid" + env.color + "; background-color: #f9f9f9; padding: 15px; margin: 20px 0; font-family: Arial, sans-serif; box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1); border-radius: 8px;\"><div style=\"position: absolute; top: -0.85em; left: 15px; background-color:" + env.color + "; padding: 0 5px; font-weight: bold; color: #f9f9f9; border: 2px solid" + env.color + ";\">" + "<span id=" + id_initial + ">" + env.name.charAt(0).toUpperCase() + env.name.slice(1) + " " + key + "</span >" + "</div><div style=\"font-style: italic; margin-top: 0.7em;\">" + body + "</div><div style=\"position: absolute; bottom: 10px; right: 10px; text-align: right; font-size: 20px; color:" + env.color + "; margin-top: 1px;\">" + env.shape + "</div></div>";
      });
    });
    // Return the modified markdown content
    return markdown;
  },

  onDidParseMarkdown: async function (html) {
    return html;
  },
})

渲染结果如下图: Screenshot 2024-09-24 at 23 16 09

我设置的语法是:

// for environment:
::: theorem {#theorem:fisher_theorem}
Theorem body
:::

// for reference:
see [@theorem:fisher_theorem](#theorem:fisher_theorem)

我通过正则表达式查找并直接替换成html。

可以把类似的定理环境加到这个repository中吗?我写数学公式用会经常用公式和定理环境。当然我上面的方法肯定不是最优的,给出的style仅供参考。期待您的回复,谢谢!

YangFong commented 1 month ago

若是你的想法是加入高亮块,比如下面这样的:

[!NOTE]
Highlights information that users should take into account, even when skimming.

[!TIP] Optional information to help a user be more successful.

[!IMPORTANT]
Crucial information necessary for users to succeed.

[!WARNING]
Critical content demanding immediate user attention due to potential risks.

[!CAUTION] Negative potential consequences of an action.

那么我也是有想过的,有找到对应的库,可以快速实现,不过暂时还未落实。

参见:

Jieli12 commented 1 month ago

类似高亮块,但是我想要的效果是类似上面的定理截图。其实另一个思路是借用高亮块的class,然后再自己重新设置CSS即可,不知道这样是否可行?我不是非常熟悉Vue, JS, TS,所以只是泛泛而谈,谢谢回复,期待更新!

YangFong commented 1 month ago

设定一个标记规则,并渲染高亮块,高亮块主要有标题、标识、主题背景或边框,还有内容。

而样式可以先不管,都是可以 div 的,主要是定好触发规则和渲染的基础内容。

我们可以支持该规则,并预设一套基础样式,有其他样式的需求,则可以自己手动修改。

Jieli12 commented 1 month ago

Thank you very much, well done!