Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions package-lock.json

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

4 changes: 3 additions & 1 deletion packages/plugin-docs-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@
"github-slugger": "^1.5.0",
"gray-matter": "^4.0.3",
"hast-util-to-html": "^9.0.0",
"minimist": "^1.2.8"
"marked": "^16.3.0",
"minimist": "^1.2.8",
"xss": "^1.0.15"
Comment thread
sunker marked this conversation as resolved.
},
"devDependencies": {
"@types/debug": "^4.1.12",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: Overview
description: Landing page for the test docs
sidebar_position: 0
---

Welcome to the test docs. See the [guide](./guide) for details, or visit [Grafana](https://grafana.com).
15 changes: 15 additions & 0 deletions packages/plugin-docs-cli/src/__fixtures__/test-readme/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Test Plugin

This is the plugin readme, shown on the Overview tab.

## Getting started with `grafana-cli`

Install the plugin and open Grafana.

### Prerequisites

Run Grafana v10 or later.

## Screenshots

See below.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: Overview
description: Landing page for the unsafe-slug fixture
---

Landing page for the unsafe-slug fixture.
4 changes: 2 additions & 2 deletions packages/plugin-docs-cli/src/bin/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { stat } from 'node:fs/promises';
import minimist from 'minimist';
import createDebug from 'debug';
import { resolvePluginJson } from '../utils/utils.plugin.js';
import { readmeCandidates, resolvePluginJson } from '../utils/utils.plugin.js';
import { serve } from '../commands/serve.command.js';
import { buildDocs } from '../commands/build.command.js';
import { validateCommand } from '../commands/validate.command.js';
Expand Down Expand Up @@ -69,7 +69,7 @@ async function main() {
reload: false,
},
});
await serve(serveArgv, docsPath, pluginType);
await serve(serveArgv, docsPath, pluginType, readmeCandidates());
break;
}
case 'build': {
Expand Down
9 changes: 5 additions & 4 deletions packages/plugin-docs-cli/src/commands/build.command.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ describe('build', () => {
const manifest = JSON.parse(await readFile(manifestPath, 'utf-8'));

expect(manifest.version).toBe('1');
expect(manifest.pages).toHaveLength(4);
expect(manifest.pages[0].title).toBe('Home Page');
expect(manifest.pages[0].slug).toBe('home');
expect(manifest.pages).toHaveLength(5);
expect(manifest.pages[0].slug).toBe('index');
expect(manifest.pages[1].title).toBe('Home Page');
expect(manifest.pages[1].slug).toBe('home');
});

it('should inline frontmatter and content into manifest.json, self-contained', async () => {
Expand All @@ -39,7 +40,7 @@ describe('build', () => {
const manifestPath = join(tmpDir, 'dist', 'docs', 'manifest.json');
const manifest = JSON.parse(await readFile(manifestPath, 'utf-8'));

const home = manifest.pages[0];
const home = manifest.pages.find((p: { slug: string }) => p.slug === 'home');
expect(home.frontmatter).toEqual({
title: 'Home Page',
description: 'Welcome to the test docs',
Expand Down
8 changes: 7 additions & 1 deletion packages/plugin-docs-cli/src/commands/serve.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import { startServer } from '../server/server.js';

const debug = createDebug('plugin-docs-cli:serve');

export const serve = async (argv: minimist.ParsedArgs, docsPath: string, pluginType?: string) => {
export const serve = async (
argv: minimist.ParsedArgs,
docsPath: string,
pluginType?: string,
readmePaths?: string[]
) => {
debug('Serve command invoked with args: %O', argv);

// parse port
Expand All @@ -19,6 +24,7 @@ export const serve = async (argv: minimist.ParsedArgs, docsPath: string, pluginT
try {
await startServer({
docsPath,
readmePaths,
port,
liveReload,
pluginType,
Expand Down
45 changes: 24 additions & 21 deletions packages/plugin-docs-cli/src/scanner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('scanDocsFolder', () => {
expect(result.manifest).toBeDefined();
expect(result.manifest.version).toBe('1');
expect(result.manifest.title).toBe('Plugin Documentation');
expect(result.manifest.pages).toHaveLength(4); // home, guide, advanced, config
expect(result.manifest.pages).toHaveLength(5); // index, home, guide, advanced, config
});

it('should sort root index.md first even when sidebar_position is not set', async () => {
Expand All @@ -27,54 +27,57 @@ describe('scanDocsFolder', () => {
const result = await scanDocsFolder(testDocsPath);

const pages = result.manifest.pages;
expect(pages[0].title).toBe('Home Page');
expect(pages[0].slug).toBe('home');
expect(pages[1].title).toBe('User Guide');
expect(pages[1].slug).toBe('guide');
expect(pages[2].title).toBe('Advanced Topics');
expect(pages[2].slug).toBe('advanced');
expect(pages[0].slug).toBe('index');
expect(pages[1].title).toBe('Home Page');
expect(pages[1].slug).toBe('home');
expect(pages[2].title).toBe('User Guide');
expect(pages[2].slug).toBe('guide');
expect(pages[3].title).toBe('Advanced Topics');
expect(pages[3].slug).toBe('advanced');
});

it('should generate slugs from file paths', async () => {
const result = await scanDocsFolder(testDocsPath);

const pages = result.manifest.pages;
expect(pages[0].slug).toBe('home');
expect(pages[1].slug).toBe('guide');
expect(pages[2].slug).toBe('advanced');
expect(pages[0].slug).toBe('index');
expect(pages[1].slug).toBe('home');
expect(pages[2].slug).toBe('guide');
expect(pages[3].slug).toBe('advanced');
});

it('should load file contents into memory (frontmatter stripped)', async () => {
const result = await scanDocsFolder(testDocsPath);

expect(result.files).toBeDefined();
expect(Object.keys(result.files)).toHaveLength(6); // includes nested config files + index
expect(Object.keys(result.files)).toHaveLength(7); // index, home, guide, advanced, config/index, config/settings, config/database
expect(result.files['home.md']).toContain('# Welcome');
expect(result.files['home.md']).not.toContain('---');
});

it('should attach frontmatter and content to each page in the manifest', async () => {
const result = await scanDocsFolder(testDocsPath);

const home = result.manifest.pages[0];
expect(home.frontmatter).toEqual({
const home = result.manifest.pages.find((p: Page) => p.slug === 'home');
expect(home?.frontmatter).toEqual({
title: 'Home Page',
description: 'Welcome to the test docs',
sidebar_position: 1,
});
expect(home.content).toContain('# Welcome');
expect(home.content).not.toContain('---');
expect(home?.content).toContain('# Welcome');
expect(home?.content).not.toContain('---');
// page.content matches what the flat files map holds for the same file
expect(home.content).toBe(result.files[home.file]);
expect(home?.content).toBe(result.files[home!.file]);
});

it('should include file reference in page object', async () => {
const result = await scanDocsFolder(testDocsPath);

const pages = result.manifest.pages;
expect(pages[0].file).toBe('home.md');
expect(pages[1].file).toBe('guide.md');
expect(pages[2].file).toBe('advanced.md');
expect(pages[0].file).toBe('index.md');
expect(pages[1].file).toBe('home.md');
expect(pages[2].file).toBe('guide.md');
expect(pages[3].file).toBe('advanced.md');
});

it('should extract h2/h3 headings into page objects', async () => {
Expand Down Expand Up @@ -115,8 +118,8 @@ describe('scanDocsFolder', () => {
const unsafeSlugPath = join(__dirname, '__fixtures__', 'unsafe-slug-docs');
const result = await scanDocsFolder(unsafeSlugPath);

expect(result.manifest.pages).toHaveLength(1);
expect(result.manifest.pages[0].slug).toBe('home');
expect(result.manifest.pages).toHaveLength(2);
expect(result.manifest.pages.find((p: Page) => p.title === 'Unsafe Slug Test')?.slug).toBe('home');
});

describe('nested directories', () => {
Expand Down
Loading
Loading