atom-community / markdown-preview-plus

Markdown Preview + Community Features
https://atom.io/packages/markdown-preview-plus
Other
370 stars 85 forks source link

Code highlight in preview disappeared when code contains more than 50 lines #474

Closed KimbingNg closed 3 years ago

KimbingNg commented 4 years ago

Code highlight in preview disappeared when code contains more than 50 lines

image

lierdakil commented 4 years ago

Can't reproduce with typescript grammar and over 140 lines, so the issue is probably elsewhere. Please provide the Markdown source that the issue happens on. If this is a non-core Atom grammar, please also provide the name of the grammar package.

KimbingNg commented 4 years ago

Here is the Markdown source:the highlight display normally only when I delete a part of code and leave the code within 50 lines,

## Code
* part one

    ```java
    package com.liveyc.eloan.base.service.impl;

    import java.util.Date;
    import java.util.Properties;
    import java.util.UUID;

    import javax.mail.internet.MimeMessage;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.mail.javamail.JavaMailSenderImpl;
    import org.springframework.mail.javamail.MimeMessageHelper;
    import org.springframework.stereotype.Service;

    import com.liveyc.eloan.base.dao.EmailverifyDao;
    import com.liveyc.eloan.base.domain.Emailverify;
    import com.liveyc.eloan.base.service.IEmailVerifyService;
    import com.liveyc.eloan.base.util.DateUtil;
    import com.liveyc.eloan.util.BidConst;
    import com.liveyc.eloan.util.UserContext;

    @Service
    public class EmailVerifyServiceImpl implements IEmailVerifyService {

        @Autowired
        private EmailverifyDao emailverifyDao;

        @Value("${mail.host}")
        private String host;

        @Value("${mail.smtpHost}")
        private String smtpHost;

        @Value("${mail.username}")
        private String username;

        @Value("${mail.password}")
        private String password;

        /**
         * http://localhost:8080/checkEmailBind.do?key=4f399b0b-c17b-4e9d-9abc-0
         * c816cd474bb 1,得到当前用户,得到要绑定的邮箱,绑定的时间,生成一个随机码--->EmailVerify;
         * 2,发送一封邮件;在邮件的这里(http://localhost/checkEmailBind.do?key=随机码)
         */
        @Override
        public void sendVerifyEmail(String email) {
            Emailverify ev = new Emailverify();
            ev.setUserinfoId(UserContext.getCurrent().getId());
            ev.setEmail(email);
            ev.setSendTime(new Date());
            ev.setUuid(UUID.randomUUID().toString().replace("-", ""));

            // 构造邮件内容
            StringBuilder content = new StringBuilder(100)
                    .append("<html><head></head><body><h1>这是你在蓝源Eloan网站的验证邮件,请点击<a href='")
                    .append(host).append("checkEmailBind.do?key=")
                    .append(ev.getUuid()).append("'>").append("这里").append("</a>")
                    .append("完成邮箱绑定,有效期为"+BidConst.EMAIL_VALID_DAY+"天</h1></body></html>");

            System.out.println(content);

            try {
                sendEmail(email, "绑定邮箱验证邮件", content.toString());
                this.emailverifyDao.insert(ev);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        }

        /**
         * 发送邮件
         *
         * @param email
         * @param string
         * @param string2
         */
        private void sendEmail(String email, String subject, String content)
                throws Exception {
            JavaMailSenderImpl senderImpl = new JavaMailSenderImpl();

            // 设置发送邮件的SMTP服务器地址
            senderImpl.setHost(smtpHost);

            // 创建一个邮件对象
            MimeMessage mailMessage = senderImpl.createMimeMessage();

            // 创建邮件对象的服务类
            MimeMessageHelper messageHelper = new MimeMessageHelper(mailMessage,"UTF-8");

            messageHelper.setTo(email);// 设置发给谁
            messageHelper.setFrom(username);// 发件人
            messageHelper.setSubject(subject);// 设置邮件标题
            messageHelper.setText(content, true);// 设置邮件内容

            senderImpl.setUsername(username); // 根据自己的情况,设置username
            senderImpl.setPassword(password);// 设置密码

            Properties prop = new Properties();
            prop.put("mail.smtp.auth", "true");// 设置发送邮件需要身份认证
            prop.put("mail.smtp.timeout", "25000");// 设置发送超时时间
            senderImpl.setJavaMailProperties(prop);

            senderImpl.send(mailMessage);
        }

        /**
         * 获取请求中的随机码;
         *
         * 2,根据随机码得到EmailVerify对象; 3,只需要验证时间是否超时; 4,把emailverify中的邮箱地址绑定到指定用户上;
         */
        @Override
        public Emailverify verifyEmail(String key) {
            Emailverify ev = this.emailverifyDao.selectByUuid(key);
            if (ev != null
                   && DateUtil.getSecondsBetweenDates(ev.getSendTime(), new Date()) <= 3600 * 24 * BidConst.EMAIL_VALID_DAY) {
                return ev;
            }
            return null;
        }

    }


## This is what the preview panel looks like.
![image](https://user-images.githubusercontent.com/50580578/68582780-89c26980-04b6-11ea-9a53-3e3fce0923a0.png)
KimbingNg commented 4 years ago

And the issue also happens with typescript and 50 lines in my computer... 😢

But this does not happen every time

lierdakil commented 4 years ago

What Atom version are you using?

lierdakil commented 4 years ago

Nevermind, was able to reproduce it using the example you provided.

KimbingNg commented 4 years ago

Atom 1.40.1 x64 image

lierdakil commented 4 years ago

After a few hours of experimentation, I think I might have fixed it in v3.11.4, but due to it not manifesting every time, I can't really be sure. Could you test to see if v3.11.4 works on your end? Thanks.

KimbingNg commented 4 years ago

Thank you sooo much !!

but on my end, v3.11.4 works imperfectly. Issue on JAVA grammar might has been fixed, but something still goes wrong with typescript grammar

Here is the source:


* ## Not fixed:

    ```ts
    import url = require('url')
    import {
      SerializedMPV,
      MarkdownPreviewViewFile,
      MarkdownPreviewViewEditor,
      MarkdownPreviewView,
    } from './markdown-preview-view'
    // import mathjaxHelper = require('./mathjax-helper')
    import {
      TextEditor,
      WorkspaceOpenOptions,
      CommandEvent,
      CompositeDisposable,
      ContextMenuOptions,
    } from 'atom'
    import * as util from './util'
    import { PlaceholderView } from './placeholder-view'
    import { migrateConfig } from './migrate-config'
    import { MarkdownPreviewViewEditorRemote } from './markdown-preview-view/markdown-preview-view-editor-remote'

    export { config } from './config'

    let disposables: CompositeDisposable | undefined

    export async function activate() {
      if (migrateConfig()) {
        atom.notifications.addInfo(
          'Markdown-Preivew-Plus has updated your config to a new format. ' +
            'Please check if everything is in order. ' +
            'This message will not be shown again.',
          { dismissable: true },
        )
      }
      if (atom.packages.isPackageActive('markdown-preview')) {
        await atom.packages.deactivatePackage('markdown-preview')
      }
      if (!atom.packages.isPackageDisabled('markdown-preview')) {
        atom.packages.disablePackage('markdown-preview')
        atom.notifications.addInfo(
          'Markdown-preview-plus has disabled markdown-preview package.',
          { dismissable: true },
        )
      }
      disposables = new CompositeDisposable()
      disposables.add(
        atom.commands.add('.markdown-preview-plus', {
          'markdown-preview-plus:toggle': close,
        }),
        atom.commands.add('atom-workspace', {
          'markdown-preview-plus:select-syntax-theme': async () => {
            try {
              const { selectListView } = await import('./select-list-view')
              const themeNames = atom.themes.getLoadedThemeNames()
              if (themeNames === undefined) return
              const theme = await selectListView(
                themeNames.filter((x) => x.match(/-syntax$/)),
              )
              if (theme === undefined) return
              atom.config.set('markdown-preview-plus.syntaxThemeName', theme)
            } catch (e) {
              const err = e as Error
              atom.notifications.addFatalError(err.name, {
                detail: err.message,
                stack: err.stack,
              })
            }
          },
        }),
        atom.commands.add('atom-text-editor', {
          'markdown-preview-plus:toggle-render-latex': (e) => {
            const editor = e.currentTarget.getModel()
            const view = MarkdownPreviewViewEditor.viewForEditor(editor)
            if (view) view.toggleRenderLatex()
          },
        }),
        atom.commands.add('.markdown-preview-plus', {
          'markdown-preview-plus:toggle-render-latex': (e) => {
            const view = MarkdownPreviewView.viewForElement(e.currentTarget)
            if (view) view.toggleRenderLatex()
          },
        }),
        atom.workspace.addOpener(opener),
        atom.config.observe(
          'markdown-preview-plus.grammars',
          configObserver(registerGrammars),
        ),
        atom.config.observe(
          'markdown-preview-plus.extensions',
          configObserver(registerExtensions),
        ),
      )
    }

    export function deactivate() {
      disposables && disposables.dispose()
    }

    export function createMarkdownPreviewView(state: SerializedMPV) {
      if (state.editorId !== undefined) {
        return new PlaceholderView(state.editorId)
      } else if (state.filePath && util.isFileSync(state.filePath)) {
        return new MarkdownPreviewViewFile(state.filePath)
      }
      return undefined
    }

    /// private

    async function close(event: CommandEvent<HTMLElement>): Promise<void> {
      const item = MarkdownPreviewView.viewForElement(event.currentTarget)
      if (!item) return
      const pane = atom.workspace.paneForItem(item)
      if (!pane) return
      await pane.destroyItem(item)
    }

    async function toggle(editor: TextEditor) {
      if (removePreviewForEditor(editor)) return undefined
      else return addPreviewForEditor(editor)
    }

    function removePreviewForEditor(editor: TextEditor) {
      const item = MarkdownPreviewViewEditor.viewForEditor(editor)
      if (!item) return false
      const previewPane = atom.workspace.paneForItem(item)
      if (!previewPane) return false
      if (item !== previewPane.getActiveItem()) {
        previewPane.activateItem(item)
        return false
      }
      util.handlePromise(previewPane.destroyItem(item))
      return true
    }
KimbingNg commented 4 years ago

Another example here:

* ## works perfectly
    ```cpp
    #include <algorithm>
    #include <iostream>
    #include <set>
    #include <vector>

    using namespace std;
    typedef long long ll;

    ll powMod(ll a, ll k, ll p) {
        a %= p;
        ll ans = 1;
        while (k) {
            if (k & 1) ans = ans * a % p;
            a = a * a % p;
            k >>= 1;
        }
        return ans;
    }
lierdakil commented 4 years ago

I can't repro with 3.11.4 using you examples. Not entirely sure why. However, I did try tweaking some things in 3.11.5, that might at least help with the issue somewhat (or might change nothing, that is also possible).

KimbingNg commented 4 years ago

still no highlight when more than 100 lines or 150 .....

However, I found that when I change the markdown code from c to cs, It surprisingly works !

like

no highlight with: ```c int i; // 50 lines ```

highlight with ```cs int i; // 50 lines ```

Java and other language also work, only c/cpp or js dosn't.

I generated the html code to find the reason, I found that When the code is more than 100 lines, the generated html code does not distinguish the keywords of the c code at all, so it is not highlighted.

<span>int main(int argc, char *argv[]) {</span>

code less than 100 lines could generate the right html like

<span class="syntax--support syntax--storage syntax--type">int</span>
<span class="syntax--entity syntax--name syntax--function">main</span>
<span class="syntax--punctuation syntax--section syntax--parens syntax--begin syntax--bracket syntax--round">(</span>
<span class="syntax--support syntax--storage syntax--type">int</span>
lierdakil commented 4 years ago

This might be an issue specific to tree-sitter parsers. If it's all the same to you, you might try disabling tree-sitter parsers in Atom settings to see if that helps.

Honestly, I have no idea what I could do here besides using a home-grown syntax highlighter instead of Atom's built-in one (which in many aspects would be a downgrade). Long story short, Atom's syntax highlighting seemingly just "gives up" for some reason when used in background, stops tokenizing input at one point or another, and reports that it's all done.

lierdakil commented 3 years ago

A quick heads-up, I bit the bullet and reimplemented the highlighter back in July. Seemingly that fixed this issue. Some other kinks were ironed out in v4.8.2. Feel free to open new issues if the problem persists.