Skip to content
This repository has been archived by the owner on May 13, 2024. It is now read-only.

[Question] How can I get parsed markdown from vuepress-plugin-container? #20

Closed
YunYouJun opened this issue Feb 2, 2020 · 14 comments
Closed
Labels
enhancement New feature or request stale

Comments

@YunYouJun
Copy link

YunYouJun commented Feb 2, 2020

Environment

  • Package version: vuepress-plugin-containerx@2.1.2
  • VuePress version: vuepress@1.2.0
  • OS: Mac OS Catalina 10.15.3
  • Browser: Chrome 79.0.3945.130

What's your question?

How can I get parsed markdown from vuepress-plugin-container?
I cannot find it in docmention.

I want to implement a demo type container.

I just need input:

::: demo
<button class="demo">demo</button>
:::

Then I can get:

image

and display its code:

<button class="demo">demo</button>

But I cannot get the code in markdown.

By the way, I think this is a useful function. It can be added as a default feature like :::tip.

@meteorlxy
Copy link
Member

meteorlxy commented Feb 2, 2020

What do you mean by "get parsed markdown"?

Do you want to get the literal code, rather than HTML rendered? So why not wrap it in markdown code block?

::: demo
```html
<button class="demo">demo</button>
```
:::

@meteorlxy
Copy link
Member

Uh I guess I got your point. You want to get both "rendered HTML" and "literal code" in the mean time.

An interesting feature. I have no good idea for now.

Maybe there are two different ways for this:

  • Pure markdown-it
  • markdown-it + vue

🤔

@meteorlxy
Copy link
Member

Currently we repeat the code for demo. You can check how vuepress official docs does:

https://github.com/vuejs/vuepress/blame/master/packages/docs/docs/guide/markdown.md#L90-L100

@meteorlxy meteorlxy added enhancement New feature or request plugin:container labels Feb 2, 2020
@YunYouJun
Copy link
Author

Yeah! Thank you for your reply.
I think it is a good feature for docs.
Maybe this can be a [Feature request]?

@meteorlxy
Copy link
Member

In fact I think it is out of scope of plugin-container. We can make it another plugin, or intergrate it into vuepress' default theme

@YunYouJun
Copy link
Author

I find bootstrap and element both use similar features.

Bootstrap use hugo-plugin.
button.md - bootstrap

And element write some configs about markdown-it.
md-loader - element

@meteorlxy
Copy link
Member

I see. ElementUI is using "markdown-it + vue" way as I mentioned above. See https://github.com/ElemeFE/element/blob/0706805226cc8ad90011a568c1a14bf0701abd37/examples/components/demo-block.vue

@YunYouJun
Copy link
Author

Yeah, I also used this method to implement the container of demo.
I think this way is more convenient for users to customize styles and layouts.

@henrikruscon
Copy link

I did the same but I have issues with the script part of demo code. For example if I got two components going through the demo, they seem to apply as a parent and overwrite each other. So the last demo I made is the only script that goes through.

Meaning I can't have multiple demo examples on the same page. Not sure why, can't see the difference between method and Elements method.

Anyone else have that issue?

@henrikruscon
Copy link

This part handles displaying the code to a PrismJS component I created in Vue. Works well. Now to handle the rendering of the demo-component tag.

markdown: {
        extendMarkdown: (markdown) => {
            markdown.renderer.rules.fence = (tokens, idx, options, env, self) => {
                const token = tokens[idx]
                const prevToken = tokens[idx - 1]
                const isInDemoComponent = prevToken && prevToken.nesting === 1 && prevToken.info.trim().match(/^demo\s*(.*)$/)
                
                if (token.info === 'html' && isInDemoComponent) {
                    return `<template slot="code">${markdown.utils.escapeHtml(token.content)}</template>`
                }
            }
            
            markdown.use(require('markdown-it-container'), 'demo', {
                    validate: (params) => {
                        return params.trim().match(/^demo\s*(.*)$/)
                    },
                    
                    render: (tokens, idx) => {
                        const { nesting, info } = tokens[idx]
                        const nextToken = tokens[idx + 1]
                        const content = nextToken.type === 'fence' ? nextToken.content : ''
                        
                        if (nesting === 1) {
                            return `
                                <DemoComponent>
                                    <!--demo-component: ${content} :demo-component-->
                            `
                        }
                        
                        return '</DemoComponent>'
                }
            })
        }
    },

The previous method I used to render the components failed to handle script tags well. Like I mentioned previously, they kept replacing one an other if there was multiple ones.

Hoping this new approach based on ElementUI will solve it, will comment again if I find a good solution for that part.

@YunYouJun
Copy link
Author

@henrikdahl Looks good!
BTW, I found two plugins about demo code.
vuepress-plugin-demo-code
vuepress-plugin-demo-block

@henrikruscon
Copy link

henrikruscon commented Mar 5, 2020

@YunYouJun Thanks! Also thanks for sharing.

vuepress-plugin-demo-code has the same bug I mentioned above. Was using that one as a reference to begin with.

The other one doesn't use a Vue component as a base which is a requirement for me. I'm thinking it might share the same bug as well. Haven't tried that one.

I got it to render both the code and the demo part, however the script tag throws an error and hence the components don't work properly.

Expanded:
Screenshot 2020-03-05 at 16 03 12
Imploded:
Screenshot 2020-03-05 at 16 07 24

Any suggestions? How did you get script tags working properly? With two way binding (v-model) and such?

@YunYouJun
Copy link
Author

YunYouJun commented Mar 5, 2020

In fact, I didn't find this problem until you mentioned it.

I think it may be caused by script-style-hoisting.

I tried it and no better method found.


Since they both need export default, I think maybe you can write them in .vuepress/componets.
Then import them by import-code-snippets.

.vupress/components/test-demo1

<template>
  <input :disabled="disabled" />
</template>

<script>
export default {
  data() {
    return {
      disabled: true
    };
  }
};
</script>

.vupress/components/test-demo2

<template>
  <input :disabled="disabled" />
</template>

<script>
export default {
  data() {
    return {
      disabled: false
    };
  }
};
</script>

Docs markdown

<test-demo1/>

<<< @/docs/.vuepress/components/test-demo1.vue

<test-demo2/>

<<< @/docs/.vuepress/components/test-demo2.vue

It works.
QQ20200306-002241@2x.png

@stale
Copy link

stale bot commented May 4, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label May 4, 2020
@stale stale bot closed this as completed May 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request stale
Projects
None yet
Development

No branches or pull requests

3 participants