This is an automated email from the ASF dual-hosted git repository.
guoqi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-website.git
The following commit(s) were added to refs/heads/master by this push:
new f2c8a6bbf33 ci: lint markdown frontmatter (#2032)
f2c8a6bbf33 is described below
commit f2c8a6bbf3360a680c2a8e20b8b262507bec5706
Author: Qi Guo <[email protected]>
AuthorDate: Thu Apr 16 15:40:59 2026 +0800
ci: lint markdown frontmatter (#2032)
---
.github/workflows/lint.yml | 11 +++++++
package.json | 2 ++
scripts/lint-frontmatter.js | 70 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 83 insertions(+)
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index e9ea7577503..a89cf69beef 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -14,6 +14,17 @@ jobs:
node-version: '12.x'
- run: npm install -g [email protected]
- run: markdownlint '**/*.md' --ignore node_modules
+ frontmatter:
+ name: 🍒 Frontmatter
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/[email protected]
+ - name: 🚀 Use Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: '16.x'
+ - run: yarn install --frozen-lockfile --ignore-scripts
+ - run: yarn lint:frontmatter
yamllint:
name: 🍏 YAML
runs-on: ubuntu-latest
diff --git a/package.json b/package.json
index 24681a8f15a..cd5e20fe3c8 100644
--- a/package.json
+++ b/package.json
@@ -39,6 +39,7 @@
"serve:doc": "yarn workspace doc docusaurus serve",
"serve:blog:zh": "yarn workspace blog docusaurus serve zh",
"serve:blog:en": "yarn workspace blog docusaurus serve en",
+ "lint:frontmatter": "node scripts/lint-frontmatter.js",
"build:website:preview:serve": "yarn build:website:preview && yarn
serve:website",
"build:doc:preview:serve": "yarn build:doc:preview && yarn serve:doc",
"build:blog:zh:preview:serve": "yarn build:blog:zh:preview && yarn
serve:blog:zh",
@@ -60,6 +61,7 @@
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-yml": "^0.14.0",
"husky": ">=6",
+ "js-yaml": "^4.1.0",
"lint-staged": ">=10",
"remark": "^14.0.2",
"remark-cli": "^11.0.0",
diff --git a/scripts/lint-frontmatter.js b/scripts/lint-frontmatter.js
new file mode 100644
index 00000000000..9464beeda01
--- /dev/null
+++ b/scripts/lint-frontmatter.js
@@ -0,0 +1,70 @@
+/* eslint-disable no-console */
+const fs = require('fs');
+const path = require('path');
+const yaml = require('js-yaml');
+
+const ROOT = path.resolve(__dirname, '..');
+const IGNORED_DIRS = new Set([
+ '.git',
+ 'build',
+ 'dist',
+ 'node_modules',
+]);
+const MARKDOWN_EXTENSIONS = new Set(['.md', '.mdx']);
+
+function walk(dir, files = []) {
+ fs.readdirSync(dir, { withFileTypes: true }).forEach((entry) => {
+ if (entry.isDirectory()) {
+ if (!IGNORED_DIRS.has(entry.name)) {
+ walk(path.join(dir, entry.name), files);
+ }
+ return;
+ }
+
+ if (entry.isFile() && MARKDOWN_EXTENSIONS.has(path.extname(entry.name))) {
+ files.push(path.join(dir, entry.name));
+ }
+ });
+
+ return files;
+}
+
+function extractFrontmatter(content) {
+ if (!content.startsWith('---\n') && !content.startsWith('---\r\n')) {
+ return null;
+ }
+
+ const lines = content.split(/\r?\n/);
+ const closingIndex = lines.slice(1).findIndex((line) => line.trim() ===
'---');
+ if (closingIndex >= 0) {
+ return lines.slice(1, closingIndex + 1).join('\n');
+ }
+
+ throw new Error('Missing closing frontmatter delimiter');
+}
+
+function main() {
+ const failures = [];
+
+ walk(ROOT).forEach((file) => {
+ const relativePath = path.relative(ROOT, file);
+ const content = fs.readFileSync(file, 'utf8');
+
+ try {
+ const frontmatter = extractFrontmatter(content);
+ if (frontmatter !== null) {
+ yaml.load(frontmatter);
+ }
+ } catch (error) {
+ failures.push(`${relativePath}: ${error.message}`);
+ }
+ });
+
+ if (failures.length > 0) {
+ console.error('Invalid Markdown frontmatter found:\n');
+ failures.forEach((failure) => console.error(`- ${failure}`));
+ process.exit(1);
+ }
+}
+
+main();