Skip to content

Commit 354e439

Browse files
committed
feat(cli): support partially linking .md files
Currently, running `mermaid-chart link test/fixtures/partially-linked-markdown-file.md` fails if the markdown file has some diagrams that are already linked. Now, already linked diagrams are ignored if they're located within a markdown file.
1 parent cdf549e commit 354e439

File tree

5 files changed

+72
-10
lines changed

5 files changed

+72
-10
lines changed

packages/cli/src/commander.test.ts

+27-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ import type { MCDocument, MCProject, MCUser } from '@mermaidchart/sdk/dist/types
1313
const CONFIG_AUTHED = 'test/fixtures/config-authed.toml';
1414
/** Markdown file that has every Mermaid diagrams already linked */
1515
const LINKED_MARKDOWN_FILE = 'test/fixtures/linked-markdown-file.md';
16-
/** Markdown file that has some unlinked Mermaid diagrams */
16+
/** Markdown file that has some linked and some unlinked Mermaid diagrams */
17+
const PARTIALLY_LINKED_MARKDOWN_FILE = 'test/fixtures/partially-linked-markdown-file.md';
18+
/** Markdown file that has unlinked Mermaid diagrams */
1719
const UNLINKED_MARKDOWN_FILE = 'test/fixtures/unlinked-markdown-file.md';
1820

1921
type Optional<T> = T | undefined;
@@ -297,6 +299,30 @@ describe('link', () => {
297299
expect(file).toMatch(`id: ${mockedEmptyDiagram.documentID}\n`);
298300
expect(file).toMatch(`id: second-id\n`);
299301
});
302+
303+
it('should link diagrams in partially linked markdown file', async () => {
304+
const partiallyLinkedMarkdownFile = 'test/output/partially-linked-markdown-file.md';
305+
await copyFile(PARTIALLY_LINKED_MARKDOWN_FILE, partiallyLinkedMarkdownFile);
306+
307+
const { program } = mockedProgram();
308+
309+
vi.mock('@inquirer/confirm');
310+
vi.mock('@inquirer/select');
311+
vi.mocked(confirm).mockResolvedValue(true);
312+
vi.mocked(select).mockResolvedValueOnce(mockedProjects[0].id);
313+
314+
vi.mocked(MermaidChart.prototype.createDocument).mockResolvedValueOnce({
315+
...mockedEmptyDiagram,
316+
documentID: 'second-id',
317+
});
318+
await program.parseAsync(['--config', CONFIG_AUTHED, 'link', partiallyLinkedMarkdownFile], {
319+
from: 'user',
320+
});
321+
322+
const file = await readFile(partiallyLinkedMarkdownFile, { encoding: 'utf8' });
323+
324+
expect(file).toMatch(`id: second-id\n`);
325+
});
300326
});
301327

302328
describe('pull', () => {

packages/cli/src/commander.ts

+1
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ function linkCmd() {
218218
cache: linkCache,
219219
title: path,
220220
getProjectId,
221+
ignoreAlreadyLinked: false,
221222
});
222223

223224
await writeFile(path, linkedDiagram, { encoding: 'utf8' });

packages/cli/src/methods.ts

+18-9
Original file line numberDiff line numberDiff line change
@@ -39,28 +39,37 @@ interface CommonOptions {
3939
export interface LinkOptions extends CommonOptions {
4040
/** Function that asks the user which project id they want to upload a diagram to */
4141
getProjectId: (cache: LinkOptions['cache'], documentTitle: string) => Promise<string>;
42-
// cache to be shared between link calls. This object may be modified between calls.
42+
/** cache to be shared between link calls. This object may be modified between calls. */
4343
cache: Cache;
44+
/** If `true`, ignore diagrams that are already linked. */
45+
ignoreAlreadyLinked: boolean;
4446
}
4547

4648
/**
4749
* Creates a new diagram on MermaidChart.com for the given local diagram.
4850
*
4951
* @returns The diagram with an added `id: xxxx` field.
5052
*/
51-
export async function link(diagram: string, client: MermaidChart, options: LinkOptions) {
53+
export async function link(
54+
diagram: string,
55+
client: MermaidChart,
56+
{ title, getProjectId, cache, ignoreAlreadyLinked }: LinkOptions,
57+
) {
5258
const frontmatter = extractFrontMatter(diagram);
5359

5460
if (frontmatter.metadata.id) {
55-
throw new CommanderError(
56-
/*exitCode=*/ 1,
57-
'EALREADY_LINKED',
58-
'This document already has an `id` field',
59-
);
61+
if (ignoreAlreadyLinked) {
62+
console.log(`○ - ${title} is already linked`);
63+
return diagram; // no change required
64+
} else {
65+
throw new CommanderError(
66+
/*exitCode=*/ 1,
67+
'EALREADY_LINKED',
68+
'This document already has an `id` field',
69+
);
70+
}
6071
}
6172

62-
const { title, getProjectId, cache } = options;
63-
6473
const projectId = await getProjectId(cache, title);
6574

6675
const createdDocument = await client.createDocument(projectId);

packages/cli/src/remark.ts

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export function plugin({ client, ...options }: MCPluginOptions) {
5353
cache: options.cache,
5454
title: ``,
5555
getProjectId: options.getProjectId,
56+
ignoreAlreadyLinked: true,
5657
});
5758
break;
5859
case 'pull': {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Test markdown file with some linked diagrams and some unlinked diagrams
2+
3+
Here is a markdown comment: <!-- Hello World -->
4+
5+
This is a journey diagram that is already linked.
6+
7+
```mermaid
8+
---
9+
id: xxxxxxx-journey
10+
---
11+
journey
12+
title This is a linked journey diagram.
13+
section Use mermaidchart.com CLI
14+
Run link command: 5: Me
15+
Edit diagram on mermaidchart.com: 5: Me
16+
Run pull command to sync changes locally: 5: Me
17+
```
18+
19+
This is a class diagram that isn't linked.
20+
21+
```mermaid
22+
classDiagram
23+
note "From local to mermaidchart"
24+
mermaidchart <|-- local
25+
```

0 commit comments

Comments
 (0)