Skip to content

Commit

Permalink
feat(nx-dev): conformance rule for blog post description
Browse files Browse the repository at this point in the history
  • Loading branch information
juristr committed Jan 31, 2025
1 parent a92e8f2 commit f705fad
Show file tree
Hide file tree
Showing 6 changed files with 277 additions and 20 deletions.
4 changes: 4 additions & 0 deletions nx.json
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@
"defaultBase": "master",
"conformance": {
"rules": [
{
"rule": "@nx/workspace-plugin/conformance-rules/blog-description",
"projects": ["!.", "docs"]
},
{
"rule": "@nx/workspace-plugin/conformance-rules/project-package-json",
"projects": [
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@
"@nx/rsbuild": "20.4.0-beta.2",
"@nx/rspack": "20.4.0-beta.2",
"@nx/storybook": "20.4.0-beta.2",
"@nx/vite": "20.4.0-beta.2",
"@nx/web": "20.4.0-beta.2",
"@nx/webpack": "20.4.0-beta.2",
"@nx/vite": "20.4.0-beta.2",
"@phenomnomnominal/tsquery": "~5.0.1",
"@playwright/test": "^1.36.1",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
Expand All @@ -102,8 +102,8 @@
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-url": "^8.0.2",
"@rspack/core": "1.1.6",
"@rsbuild/core": "1.1.8",
"@rspack/core": "1.1.6",
"@rspack/dev-server": "1.0.9",
"@rspack/plugin-minify": "^0.7.5",
"@rspack/plugin-react-refresh": "^1.0.0",
Expand Down Expand Up @@ -136,6 +136,7 @@
"@types/jasmine": "~2.8.6",
"@types/jasminewd2": "~2.0.3",
"@types/jest": "29.5.12",
"@types/js-yaml": "^4.0.9",
"@types/marked": "^2.0.0",
"@types/node": "20.16.10",
"@types/npm-package-arg": "6.1.1",
Expand Down Expand Up @@ -227,6 +228,7 @@
"jest-runtime": "29.7.0",
"jest-util": "29.7.0",
"js-tokens": "^4.0.0",
"js-yaml": "^4.1.0",
"jsonc-eslint-parser": "^2.1.0",
"jsonc-parser": "3.2.0",
"kill-port": "^1.6.1",
Expand Down
47 changes: 29 additions & 18 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { vol } from 'memfs';
import { workspaceRoot } from '@nx/devkit';
import { join } from 'node:path';
import blogDescriptionRule from './index';

jest.mock('fs', () => require('memfs').fs);
jest.mock('@nx/devkit', () => ({
workspaceRoot: '/root',
}));

describe('blog-description', () => {
beforeEach(() => {
vol.reset();
});

it('should pass when blog posts have descriptions', async () => {
vol.fromJSON(
{
'docs/blog/post1.md': `---
title: Post 1
description: This is post 1
---
Content`,
'docs/blog/post2.md': `---
title: Post 2
description: This is post 2
---
Content`,
},
workspaceRoot
);

const result = await blogDescriptionRule.implementation({
projectGraph: {
nodes: {
blog: {
name: 'blog',
type: 'lib',
data: {
root: 'docs/blog',
},
},
},
dependencies: {},
},
ruleOptions: {},
});

expect(result.details.violations).toHaveLength(0);
});

it('should report violations for blog posts without descriptions', async () => {
vol.fromJSON(
{
'docs/blog/post1.md': `---
title: Post 1
---
Content`,
'docs/blog/post2.md': `---
title: Post 2
description: This is post 2
---
Content`,
},
workspaceRoot
);

const result = await blogDescriptionRule.implementation({
projectGraph: {
nodes: {
blog: {
name: 'blog',
type: 'lib',
data: {
root: 'docs/blog',
},
},
},
dependencies: {},
},
ruleOptions: {},
});

expect(result.details.violations).toHaveLength(1);
expect(result.details.violations[0]).toEqual({
message: 'Blog posts with frontmatter must have a description field',
sourceProject: 'blog',
file: join(workspaceRoot, 'docs/blog/post1.md'),
});
});

it('should ignore files without frontmatter', async () => {
vol.fromJSON(
{
'docs/blog/post1.md': '# Just a regular markdown file',
},
workspaceRoot
);

const result = await blogDescriptionRule.implementation({
projectGraph: {
nodes: {
blog: {
name: 'blog',
type: 'lib',
data: {
root: 'docs/blog',
},
},
},
dependencies: {},
},
ruleOptions: {},
});

expect(result.details.violations).toHaveLength(0);
});

it('should ignore files with invalid YAML', async () => {
vol.fromJSON(
{
'docs/blog/post1.md': `---
invalid: yaml: :
---
Content`,
},
workspaceRoot
);

const result = await blogDescriptionRule.implementation({
projectGraph: {
nodes: {
blog: {
name: 'blog',
type: 'lib',
data: {
root: 'docs/blog',
},
},
},
dependencies: {},
},
ruleOptions: {},
});

expect(result.details.violations).toHaveLength(0);
});
});
Loading

0 comments on commit f705fad

Please sign in to comment.