vuejs / vitepress

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

Last Updated Time in sitemap.xml #3931

Closed lemonicy closed 4 months ago

lemonicy commented 4 months ago

Describe the bug

When generating sitemap, the lastmod attribute only uses the commit time in git log, but not lastUpdated value in frontmatter.

Reproduction

No need to add any templates.

Expected behavior

If the frontmatter contains lastUpdated key, generated sitemap should use the lastUpdated value, otherwise use the commit time in git log.

I remember the behavior was right in RC versions, not very sure.

System Info

System:
  OS: Windows 11 10.0.22631
  CPU: (24) x64 13th Gen Intel(R) Core(TM) i7-13700K
  Memory: 52.88 GB / 63.77 GB
Binaries:
  Node: 20.12.2 - D:\Program Files\nodejs\node.EXE
  npm: 10.5.0 - D:\Program Files\nodejs\npm.CMD
Browsers:
  Edge: Chromium (125.0.2535.67)
  Internet Explorer: 11.0.22621.3527
npmPackages:
  vitepress: ^1.2.2 => 1.2.2

Additional context

No response

Validations

Solution (Added in 3rd June 2024)

I wrote some codes to solve this issue, maybe I can help others who searched from google.

in config.mjs or config.mts:

import fs from "fs";

export default defineConfig({
    sitemap: {
        hostname: "Your Domain",
        transformItems: (items) => {
            // Reset last updated time of sitemap.xml
            items.forEach(item => {
                const url = item.url;
                // Read the file, replace the updated time from frontmatter with the time in git log
                // My blog path is "/docs", you can replace it to yours.
                const file = "docs/" + url + ".md";
                try {
                    const data = fs.readFileSync(file, "utf-8");
                    const getUrl = data => {
                        const allLines = data.split("\n");
                        for (let i = 0; i < allLines.length; i++) {
                            const currentLine = allLines[i];
                            // the statement i > 1 can prevent the program from suspending when reading at the first line
                            if (i > 1 && currentLine === "---") {
                                console.warn("There is no lastUpdated time in Frontmatter.");
                                return null;
                            }
                            if (currentLine.indexOf("lastUpdated") >= 0) {
                                return currentLine.replace("lastUpdated:", "").trim();
                            }
                        }
                    }
                    const newUpdatedTime = getUrl(data);
                    // Only replace updated time when frontmatter value exists.
                    if (newUpdatedTime) {
                        item.lastmod = newUpdatedTime;
                    }
                } catch (err) {
                    console.error(err);
                    return false;
                }
            });
            return filteredItems;
        }
    },
});
lemonicy commented 4 months ago

VitePress Doc - Last Updated - Frontmatter Config

This can be disabled per-page using the lastUpdated option on frontmatter:

---
lastUpdated: false
---

I don't mean to disable lastUpdated option.

I have written some codes to solve this issue. The solution has been added to the main post.