vuejs / vitepress

Vite & Vue powered static site generator.
https://vitepress.dev
MIT License
13.32k stars 2.15k forks source link

better stack trace / error message for markdown-it-attrs failures #3401

Open srl295 opened 11 months ago

srl295 commented 11 months ago

I hit another case of #449 by including the following in a markdown file. The workaround which linked to #662 worked for me. Perhaps this should be off by default? Or detect the compilation error and bring a suggestion? The XML I included seems pretty straightforward. Would have been very hard to diagnose if I hadn't been doing lots of searches against the issues here.

<keyboard locale="mt" conformsTo="techpreview">
  <keys>
    <key id="hmaqtugha" to="ħ" />
    <key id="that" to="ថា" />
  </keys>

  <layers form="hardware">
    <layer id="base">
      <row keys="hmaqtugha that" />
    </layer>
  </layers>

</keyboard>

Symptom is an error deep inside vue

5:26:34 PM [vitepress] Internal server error: Duplicate attribute.
  Plugin: vite:vue
  File: /Users/srl295/src/codehivetx.us/en/posts/2022-kbd-progress.md:22:69
  22 |    <keys>
  23 |      <key id="hmaqtugha" to="ħ" />
  24 |      <key id="that" to="ថា" />
     |                            ^
  25 |    </keys>
  26 |  
      at createCompilerError (/Users/srl295/src/codehivetx.us/node_modules/@vue/compiler-core/dist/compiler-core.cjs.js:1327:17)
      at emitError (/Users/srl295/src/codehivetx.us/node_modules/@vue/compiler-core/dist/compiler-core.cjs.js:2805:5)
      at Object.onattribnameend (/Users/srl295/src/codehivetx.us/node_modules/@vue/compiler-core/dist/compiler-core.cjs.js:2290:7)
      at Tokenizer.handleAttrNameEnd (/Users/srl295/src/codehivetx.us/node_modules/@vue/compiler-core/dist/compiler-core.cjs.js:872:14)
      at Tokenizer.stateInAttrName (/Users/srl295/src/codehivetx.us/node_modules/@vue/compiler-core/dist/compiler-core.cjs.js:812:12)
      at Tokenizer.parse (/Users/srl295/src/codehivetx.us/node_modules/@vue/compiler-core/dist/compiler-core.cjs.js:1065:16)
      at Object.baseParse (/Users/srl295/src/codehivetx.us/node_modules/@vue/compiler-core/dist/compiler-core.cjs.js:2844:13)
      at Object.parse (/Users/srl295/src/codehivetx.us/node_modules/@vue/compiler-dom/dist/compiler-dom.cjs.js:698:23)
      at Object.parse$2 [as parse] (/Users/srl295/src/codehivetx.us/node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js:1846:24)
      at createDescriptor (file:///Users/srl295/src/codehivetx.us/node_modules/@vitejs/plugin-vue/dist/index.mjs:74:43) (x2)
brc-dd commented 11 months ago

The code you've shared is not reproducible. Share a minimal reproducible example in form of repo or using https://vitepress.new and, in future, please use the issue templates while filing new issues.

However, anyway, we don't intend on disabling that plugin by default. It will be too much of a breaking change as many projects are relying on it. The best we can do is create a FAQs section in our docs and mention this there.

PS: if you need attrs features but {...} syntax is causing issues, you can change the delimiters like this - https://github.com/vuejs/router/blob/922d769f21209042edcb4b07b671de2e5884c85b/packages/docs/.vitepress/config/shared.ts#L54-L57

srl295 commented 11 months ago

Sorry, I did not intend to bypass the template. My main question was about the default, which could be a default on the generator, but the other issue was locked so I could not reply there.

I'll work on a minimum example, and a pull request with suggested documentation changes… Thank you very much for vitepress.

srl295 commented 11 months ago

@brc-dd minimum example. Fails on https://vitepress.new right away (paste this in as the entirety of index.md). Syntax is from https://hexo.io where I'm migrating the content. Of course this isn't the .md I expected to be including, but the error message was not in the least helpful.

{% asset_img example.png "Some Picture" %}

Even though there's only one line (not counting the newline) the error shows up as index.md:4:67 - that's what threw me before, it was entirely the wrong line for the error. In my case it was quite a long ways away from the actual failing line.

image

through much pain i've found that the HTML being created looks like this:

    </div><p %="" asset_img="" example.png="" SomePicture="" %=""></p>

(I updated the createDescriptor() function in the stack trace by adding console.dir({source}); … Still don't know what the entire stack trace is, it's obviously partial.)

Maybe this is a bug in the attr package, it should not be creating bad output like this.

brc-dd commented 11 months ago

Yeah, so that's kind of expected. You can disable the attrs plugin or change the delimiters. We can indicate this behavior in docs/FAQs but we won't be disabling the plugin / changing the default delimiters in v1 because of its heavy usage in our as well as other docs in Vite and Vue ecosystem.

A better solution however is to properly escape that part. Like if you're trying to show your viewers that as code, you should put it inside backticks or fences. Or if that's supposed to be an image, then that's not valid markdown image. Markdown images are written like ![Some Picture](/example.png)

{% img [class names] /path/to/image [width] [height] '"title text" "alt text"' %}

should be written like (class names, width, height, title, alt are optional)

![alt text](/path/to/image 'title text'){.class .names width=100 height=100}

But the above syntax will need you to keep attrs plugin enabled (if you're using stuff inside `{...}`).
If you want to disable the attrs plugin and still specify class names or dimensions,
directly put the HTML in markdown:

<img class="class names" src="/path/to/image" width="100" height="100" title="something" alt="something" />
srl295 commented 11 months ago

@brc-dd Right. In my case, though, it was simply an error - bad content. The problem is that the error message is:

  1. obscure (There are no duplicate attrs in my file- but markdown-it-attrs created duplicate attrs in the output HTML). So it was not expected.
  2. incorrect (the line indicated was wrong, it was pointing to the unrelated XML block instead of to the curly bracket line).
  3. incomplete (the stack trace doesn't actually show the calling code that was failing)

I'll open an issue with markdown-it-attrs to reject bad input, at least as an option. And perhaps an FAQ on vitepress for the "Duplicate attribute." error.

A single percent fails on the browser with:

Uncaught (in promise) DOMException: Failed to execute 'setAttribute' on 'Element': '%' is not a valid attribute name.

So, I'd argue that markdown-it-attrs is producing invalid output (from bad input, arguably).

Can vitepress catch such an error and offer to show the intermediate content? That might be a path to helping users out here.

brc-dd commented 11 months ago

Yeah, regarding the stack trace, it's currently not proper because of markdown-it transforming markdown to vue (line mappings are currently lost here).

Can vitepress catch such an error and offer to show the intermediate content?

In this case, yeah probably. We can throw on the node side (in terminal) with proper line number.