Skip to content

Commit

Permalink
feat: getTitle supports raw strings now (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
billiegoose committed May 16, 2022
1 parent 204b070 commit 9bb4d3f
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 27 deletions.
101 changes: 76 additions & 25 deletions src/getters/__tests__/get-title.test.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,103 @@
import { parse } from '../../parse';
import { getTitle } from '../get-title';

describe('get-title', () => {
it('should return frontmatter title if present', () => {
const title = getTitle(
parse(`---
const titleInFrontMatter = `---
title: hello
---
# Other Title
Yo
`),
);

expect(title).toBe('hello');
});
`;

it('should return heading if present', () => {
const title = getTitle(
parse(`---
const titleInH1 = `---
summary: what it is about
---
# Other Title
Yo
`),
);
`;

expect(title).toBe('Other Title');
});
const titleInUnderlineH1 = `---
summary: what it is about
---
Other Title
===========
it('should return headings other than h1 if present', () => {
const title = getTitle(
parse(`what it is about
Yo
`;

const titleInH2 = `what it is about
## Other Title 2
Yo
`),
);
`;

const noTitle = `what it is about`;

describe('get-title', () => {
describe('parsed', () => {
it('should return frontmatter title if present', () => {
const title = getTitle(parse(titleInFrontMatter));

expect(title).toBe('hello');
});

it('should return # heading if present', () => {
const title = getTitle(parse(titleInH1));

expect(title).toBe('Other Title 2');
expect(title).toBe('Other Title');
});

it('should return underlined heading if present', () => {
const title = getTitle(parse(titleInUnderlineH1));

expect(title).toBe('Other Title');
});

it('should return headings other than h1 if present', () => {
const title = getTitle(parse(titleInH2));

expect(title).toBe('Other Title 2');
});

it('should return undefined if no frontmatter title and no headings', () => {
const title = getTitle(parse(noTitle));
expect(title).toBe(undefined);
});
});

it('should return undefined if no frontmatter title and no headings', () => {
const title = getTitle(parse(`what it is about`));
expect(title).toBe(undefined);
describe('raw string', () => {
it('should return frontmatter title if present', () => {
const title = getTitle(titleInFrontMatter);

expect(title).toBe('hello');
});

it('should return # heading if present', () => {
const title = getTitle(titleInH1);

expect(title).toBe('Other Title');
});

it('should not detect underlined headings, sorry not sorry', () => {
const title = getTitle(titleInUnderlineH1);

expect(title).toBe(undefined);
});

it('should return headings other than h1 if present', () => {
const title = getTitle(titleInH2);

expect(title).toBe('Other Title 2');
});

it('should return undefined if no frontmatter title and no headings', () => {
const title = getTitle(noTitle);
expect(title).toBe(undefined);
});
});
});
28 changes: 26 additions & 2 deletions src/getters/get-title.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
import { MDAST } from '../ast-types';
import { Frontmatter } from '../frontmatter';
import { getProperty } from './get-property';

// Priority: yaml title, then first heading
export const getTitle = (data?: MDAST.Root) => {
return getProperty('title', 'heading', data);
export const getTitle = (data?: MDAST.Root | string) => {
if (typeof data === 'string') {
return getTitleFromRaw(data);
} else {
return getProperty('title', 'heading', data);
}
};

function getTitleFromRaw(raw?: string) {
if (!raw) return raw;

const frontmatterBlock = Frontmatter.getFrontmatterBlock(raw);

if (frontmatterBlock) {
const title = new Frontmatter(frontmatterBlock).get('title');
if (title) {
return String(title);
}
}

// Note: This only supports #-style headings, but underlined headings are much rarer
// Sonar Cloud flagged the original version /^#+\s*(.*)$/m as super-linear, so it has
// become this rather nasty regex to emulate atomic groups / possessive qualifiers.
const match = raw?.match(/^(?=(#+))\1(?=(\s*))\2(?=(.*))\3$/m);
return match ? match[3] : void 0;
}

0 comments on commit 9bb4d3f

Please sign in to comment.