Skip to content

[feature] A smart way to support markdown template language #847

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from

Conversation

Dafrok
Copy link

@Dafrok Dafrok commented Jun 18, 2017

Problem

I met a critical problem when I followed #595 to compile markdown template in vue components.
While compiling markdown template with more than single line, the component template won't contain a root element, and the markdown specification doesn't allowed us to add a wrapper.

Input

<-- Case 1 -->
<template>
# Hello world!
## FooBar
</template>

<-- Case 2 -->
<template>
<div>
# Hello world!
## FooBar
</div>
</template>

Expect Output

<div>
  <h1>Hello world!</h1>
  <h2>FooBar</h2>
</div>

Actual Output

<-- Case 1 -->
<h1>Hello world!</h1>
<h2>FooBar</h2>

<-- Case 2 -->
<div>
# Hello world!
## FooBar
</div>

Solution

As far as I know, the dependency consolidate.js of template compiler has no plan to support markdown syntax (See details: tj/consolidate.js#45). I has added a dependency markdown-it to treat this case, because other famous markdown parsers (e.g. marked) will overwrite ids of h1 - h6 elements.

Usage

I think this is a smart way to use markdown template.

<template lang="markdown"> <!-- or `lang="md"` as an alias -->
# Foo
## Bar
</template>

@Dafrok Dafrok changed the title Support markdown template language A smarty way to support markdown template language Jun 18, 2017
@blade254353074
Copy link

If I remember correctly, markdown should support nested (html & markdown) syntax.

@Dafrok Dafrok changed the title A smarty way to support markdown template language A smart way to support markdown template language Jun 19, 2017
@Dafrok Dafrok changed the title A smart way to support markdown template language [feature] A smart way to support markdown template language Jun 19, 2017
@Jinjiang
Copy link
Member

I think it's too coupled with the template compiler. How about creating a markdown custom block to doing this job? That's more flexible.
Thanks.

@Dafrok
Copy link
Author

Dafrok commented Nov 29, 2017

Actually I know that my solution is not very suitable for vue-loader. I've tried to use markdown filter in some template engines (e.g pug), but vue-loader can not detect the changes of markdown files which is imported by template engine. It's a critical problem when using webpack-dev-server and I found no way to treat it.

@Dafrok
Copy link
Author

Dafrok commented Nov 29, 2017

I've read the documentation of custom block, I think it's no so convenient for my case. HTML and markdown and value bindings mixed everywhere, no such a single custom block can hold it. for example:

<template lang="md">
# {{title}}

## {{subtitle}} - The first Component

<x-component></x-component>

## {{subtitle}} - The Second Component

<y-component></y-component>

... and so on
</template>

<script>
import {XComponent, YComponent} from 'somewhere'
export default {
  props: ['title', 'subtitle'],
  components: {
    XComponent,
    YComponent
  }
}
</script>

@Jinjiang
Copy link
Member

Jinjiang commented Nov 29, 2017

Anyway, I think you also could try to use markdown loader parser to convert md -> html and then use vue-template-compiler to convert html -> render() in custom block (if consolidate.js won't support markdown). 🤔

@Jinjiang
Copy link
Member

Jinjiang commented Dec 2, 2017

I have tried to create a markdown-loader like:

const compiler = require('vue-template-compiler')
const marked = require('marked')

module.exports = function (markdown, map) {
  // markdown -> html
  const html = marked(markdown)
  // html -> render functions
  const { render, staticRenderFns } = compiler.compile(`<div>\n${html}</div>`)
  return `
module.exports = function (Component) {
  Component.options.render = function () {${render}}
  Component.options.staticRenderFns = [${staticRenderFns.join(',')}]
}`
}

And it worked well with:

<markdown>
# {{title}}

## {{subtitle}} - The first Component
</markdown>

<script>
export default {
  data () {
    return {
      title: 'Hello',
      subtitle: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

I think that can help you enough.

Thanks.

@Dafrok
Copy link
Author

Dafrok commented Dec 3, 2017

Well, I got it. It seems perfect.

@Dafrok Dafrok closed this Dec 3, 2017
@Jinjiang
Copy link
Member

Additionally I found another way in our test to have a look:

it('should allow adding custom html loaders', done => {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants