vuejs / vitepress

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

Inconsistent Head Configuration in VitePress #4166

Closed admin8756 closed 1 month ago

admin8756 commented 1 month ago

Describe the bug

Hello VitePress team,

I have encountered an issue with the configuration of the head element in VitePress. It seems that the current setup for dynamically setting meta tags using gray-matte is not standard, and there appears to be validation that restricts certain elements from being added to the head section.

Steps to Reproduce:

  1. Attempt to dynamically set meta tags in the head using gray-matte.
  2. Observe that the configuration is not fully compliant with standard practices.
  3. Notice potential restrictions or validation preventing other elements from being added.

Expected Behavior:

Actual Behavior:

Proposed Solution:

Additional Information:

I'm not entirely sure if this issue affects all elements, but it does seem to impact the ability to add meta tags dynamically. A review of the validation logic might be necessary to ensure flexibility in head configuration.

Thank you for your attention to this matter.


This message clearly describes the issue, provides context, and suggests a potential solution, which should help the maintainers of the project understand and address the bug.

image image image

Reproduction

head:

Expected behavior

head: meta:

System Info

win , pnpm ,vitpress 1.3.4

Additional context

No response

Validations

brc-dd commented 1 month ago

It's because of bad yaml indentation:

image
admin8756 commented 1 month ago

这是因为 yaml 缩进不好:

图像

I want to know about the hard part of Vitepress. What standard is it. I am unable to use gray matte to generate SEO configurations.

admin8756 commented 1 month ago

这是因为 yaml 缩进不好:

图像

Why doesn't it support standard configurations

head:
  meta:
    - name: description
    content: 本文介绍了console在JavaScript中的使用方法和技巧,包括状态类方法、功能类方法、性能分析、表格输出、记时、时间戳、堆栈追踪等。同时,也探讨了.这些技巧可以帮助开发者更有效地利用,console进行调试工作,提高开发效率。
    - name: keywords
    content: JavaScript
brc-dd commented 1 month ago

Why doesn't it support standard configurations

Because your version is just as non-standard as ours. There is no such spec that specifies how to add head elements using markdown.

VitePress is using what is uses for head added via config - https://vitepress.dev/reference/site-config#head

You can use JSON front matter if indentations in YAML are confusing.

admin8756 commented 1 month ago

Why doesn't it support standard configurations

Because your version is just as non-standard as ours. There is no such spec that specifies how to add head elements using markdown.

VitePress is using what is uses for head added via config - https://vitepress.dev/reference/site-config#head

You can use JSON front matter if indentations in YAML are confusing.

sorry. I don't understand You can use JSON front matter if indentations in YAML are confusing The meaning of this sentence,Can you provide a relevant document,tq~

brc-dd commented 1 month ago

I meant you can write JSON instead of YAML in frontmatter and gray-matter supports that:

---
{
  "title": "数组切块",
  "date": "2021-05-10T00:00:00.000Z",
  "head": [
    [
      "meta",
      {
        "name": "description",
        "content": "在本文中,提供了一个名为`chunkArray`的函数,该函数接收一个数组`arr`和一个整数`size`作为参数。函数使用reduce函数对数组进行递归切块处理。在每个递归步骤中,首先通过切片操作提取出指定大小的块,然后通过filter函数过滤出剩余元素。最后,将切块后的数组返回。该方法简洁易用,适合处理需要分割数组的情况。"
      }
    ],
    [
      "meta",
      {
        "name": "keywords",
        "content": "JavaScript 基础知识"
      }
    ]
  ]
}
---

# 一行代码数组切块

...

https://stackblitz.com/edit/vite-zbq7c3?file=docs/example.md

admin8756 commented 1 month ago

I meant you can write JSON instead of YAML in frontmatter and gray-matter supports that:

---
{
  "title": "数组切块",
  "date": "2021-05-10T00:00:00.000Z",
  "head": [
    [
      "meta",
      {
        "name": "description",
        "content": "在本文中,提供了一个名为`chunkArray`的函数,该函数接收一个数组`arr`和一个整数`size`作为参数。函数使用reduce函数对数组进行递归切块处理。在每个递归步骤中,首先通过切片操作提取出指定大小的块,然后通过filter函数过滤出剩余元素。最后,将切块后的数组返回。该方法简洁易用,适合处理需要分割数组的情况。"
      }
    ],
    [
      "meta",
      {
        "name": "keywords",
        "content": "JavaScript 基础知识"
      }
    ]
  ]
}
---

# 一行代码数组切块

...

https://stackblitz.com/edit/vite-zbq7c3?file=docs/example.md

It could still be like this, thank you very much.

admin8756 commented 1 month ago

Sorry, I made some attempts,I am currently using the JSON solution, but there are new errors.

---
{
  "title": "数据库范式",
  "description": "关系数据库设计必备八股文",
  "author": "leedaisen",
  "date": "2022-04-14T00:00:00.000Z",
  "tags": [
    "数据库",
    "other"
  ],
  "minutes": 8.715,
  "words": 1743,
  "head": {
    "meta": [
      {
        "name": "description",
        "content": "本文介绍了数据库范式的概念,从1NF到5NF分别阐述了不同范式的特点和应用场景。在实际应用中,我们需要根据具体需求选择合适的范式进行数据库设计。总的来说,3NF和BCNF在减少数据冗余和维护数据完整性方面表现优秀,适用于大多数场景。但对于实际应用中的数据规范化,还需要结合具体业务需求进行权衡。"
      },
      {
        "name": "image",
        "content": "https://leelaa.cn/logo.webp"
      },
      {
        "name": "keywords",
        "content": "数据库,other"
      },
      {
        "name": "og:title",
        "content": "数据库范式"
      },
      {
        "name": "og:description",
        "content": "本文介绍了数据库范式的概念,从1NF到5NF分别阐述了不同范式的特点和应用场景。在实际应用中,我们需要根据具体需求选择合适的范式进行数据库设计。总的来说,3NF和BCNF在减少数据冗余和维护数据完整性方面表现优秀,适用于大多数场景。但对于实际应用中的数据规范化,还需要结合具体业务需求进行权衡。"
      },
      {
        "name": "og:keywords",
        "content": "数据库,other"
      },
      {
        "name": "og:type",
        "content": "article"
      },
      {
        "name": "twitter:card",
        "content": "summary_large_image"
      },
      {
        "name": "twitter:image",
        "content": "https://leelaa.cn/logo.webp"
      },
      {
        "name": "twitter:title",
        "content": "数据库范式"
      },
      {
        "name": "twitter:description",
        "content": "本文介绍了数据库范式的概念,从1NF到5NF分别阐述了不同范式的特点和应用场景。在实际应用中,我们需要根据具体需求选择合适的范式进行数据库设计。总的来说,3NF和BCNF在减少数据冗余和维护数据完整性方面表现优秀,适用于大多数场景。但对于实际应用中的数据规范化,还需要结合具体业务需求进行权衡。"
      }
    ],
    "link": [
      {
        "rel": "canonical",
        "href": "https://leelaa.cn/posts/ahsuea"
      }
    ]
  }
}
---

vitepress build

vitepress v1.3.4

✓ building client + server bundles... ✖ rendering pages... build error: head.filter is not a function TypeError: head.filter is not a function at filterOutHeadDescription (file:///F:/%E9%A1%B9%E7%9B%AE/leelaa-blog/nodemodules/.pnpm/vitepress@1.3.4@algolia+client-sea

vitepress v1.3.4

✓ building client + server bundles... ✖ rendering pages... build error: head.filter is not a function TypeError: head.filter is not a function at filterOutHeadDescription (file:///F:/%E9%A1%B9%E7%9B%AE/leelaa-blog/nodemodules/.pnpm/vitepress@1.3.4@algolia+client-search@4.24.0_@types+node@22.5.1_axios@1.7.5_markdown-it-math_4t66sk5akkvvt7stdmufjikkki/node_modules/vitepress/dist/node/serve-CFRRJDfQ.js:47010:15) at renderPage (file:///F:/%E9%A1%B9%E7%9B%AE/leelaa-blog/nodemodules/.pnpm/vitepress@1.3.4@algolia+client-search@4.24.0_@types+node@22.5.1_axios@1.7.5_markdown-it-math_4t66sk5akkvvt7stdmufjikkki/node_modules/vitepress/dist/node/serve-CFRRJDfQ.js:46899:7) at async pMap.concurrency (file:///F:/%E9%A1%B9%E7%9B%AE/leelaa-blog/nodemodules/.pnpm/vitepress@1.3.4@algolia+client-search@4.24.0_@types+node@22.5.1_axios@1.7.5_markdown-it-math_4t66sk5akkvvt7stdmufjikkki/node_modules/vitepress/dist/node/serve-CFRRJDfQ.js:47087:11) at async file:///F:/%E9%A1%B9%E7%9B%AE/leelaa-blog/nodemodules/.pnpm/vitepress@1.3.4@algolia+client-search@4.24.0_@types+node@22.5.1_axios@1.7.5_markdown-it-math_4t66sk5akkvvt7stdmufjikkki/node_modules/vitepress/dist/node/serve-CFRRJDfQ.js:2618:20

brc-dd commented 1 month ago

because it's not

  "head": {
    "meta": [

head should be an array, meta is element name

  "head": [
    [
      "meta",
      ..
     ],
     [
       "meta",
       ...
      ]
  ]
admin8756 commented 1 month ago
        data.head = {
          meta: [
            { name: 'description', content: description },
            { name: 'image', content: `${WEB_HOST}/logo.webp` },
            { name: 'keywords', content: data.tags?.join(',') || '' },
            { name: 'og:title', content: data.title },
            { name: 'og:description', content: description },
            { name: 'og:keywords', content: data.tags?.join(',') || '' },
            { name: 'og:type', content: 'article' },
            { name: 'twitter:card', content: 'summary_large_image' },
            { name: 'twitter:image', content: `${WEB_HOST}/logo.webp` },
            { name: 'twitter:title', content: data.title },
            { name: 'twitter:description', content: description },
          ],
            link: [{ rel: 'canonical', href: `${WEB_HOST}/${webURL.slice(0, -3)}` }],
        };
const updatedContent = matter.stringify(markdownContent, data, { lang: 'json' });

Am I doing this wrong?

brc-dd commented 1 month ago

yes

        data.head = [
           ['meta', { name: 'description', content: description }],
           ['meta', { name: 'image', content: `${WEB_HOST}/logo.webp` }]
           ....,
           ['link', { rel: 'canonical', href: `${WEB_HOST}/${webURL.slice(0, -3)}` }]
        ]
admin8756 commented 1 month ago

yes

        data.head = [
           ['meta', { name: 'description', content: description }],
           ['meta', { name: 'image', content: `${WEB_HOST}/logo.webp` }]
           ....,
           ['link', { rel: 'canonical', href: `${WEB_HOST}/${webURL.slice(0, -3)}` }]
        ]

I think I have already solved it. Thank you for your generosity