feat(aio): allow template to position embedded ToC (#22570)

Previously the doc-viewer would insert an embedded `<aio-toc>` element
into the DOM directly after the H1 element. Now it will not do this
if there is already a such element in the doc contents.

This allows the content-author/template-developer to position the ToC
for specific cases.

PR Close #22570
This commit is contained in:
Pete Bacon Darwin 2018-03-03 13:12:08 +00:00 committed by Alex Eagle
parent 2a1e3d191f
commit 53b0fe8144
2 changed files with 45 additions and 18 deletions

View File

@ -175,6 +175,9 @@ describe('DocViewerComponent', () => {
const DOC_WITHOUT_H1 = 'Some content';
const DOC_WITH_H1 = '<h1>Features</h1>Some content';
const DOC_WITH_NO_TOC_H1 = '<h1 class="no-toc">Features</h1>Some content';
const DOC_WITH_EMBEDDED_TOC = '<h1>Features</h1><aio-toc class="embedded"></aio-toc>Some content';
const DOC_WITH_EMBEDDED_TOC_WITHOUT_H1 = '<aio-toc class="embedded"></aio-toc>Some content';
const DOC_WITH_EMBEDDED_TOC_WITH_NO_TOC_H1 = '<aio-toc class="embedded"></aio-toc>Some content';
const DOC_WITH_HIDDEN_H1_CONTENT = '<h1><i style="visibility: hidden">link</i>Features</h1>Some content';
let titleService: MockTitle;
let tocService: MockTocService;
@ -271,26 +274,45 @@ describe('DocViewerComponent', () => {
});
describe('(ToC)', () => {
it('should add an embedded ToC element if there is an `<h1>` heading', () => {
doPrepareTitleAndToc(DOC_WITH_H1);
const tocEl = getTocEl()!;
describe('needed', () => {
it('should add an embedded ToC element if there is an `<h1>` heading', () => {
doPrepareTitleAndToc(DOC_WITH_H1);
const tocEl = getTocEl()!;
expect(tocEl).toBeTruthy();
expect(tocEl.classList.contains('embedded')).toBe(true);
expect(tocEl).toBeTruthy();
expect(tocEl.classList.contains('embedded')).toBe(true);
});
it('should not add a second ToC element if there a hard coded one in place', () => {
doPrepareTitleAndToc(DOC_WITH_EMBEDDED_TOC);
expect(targetEl.querySelectorAll('aio-toc').length).toEqual(1);
});
});
it('should not add a ToC element if there is a `.no-toc` `<h1>` heading', () => {
doPrepareTitleAndToc(DOC_WITH_NO_TOC_H1);
expect(getTocEl()).toBeFalsy();
describe('not needed', () => {
it('should not add a ToC element if there is a `.no-toc` `<h1>` heading', () => {
doPrepareTitleAndToc(DOC_WITH_NO_TOC_H1);
expect(getTocEl()).toBeFalsy();
});
it('should not add a ToC element if there is no `<h1>` heading', () => {
doPrepareTitleAndToc(DOC_WITHOUT_H1);
expect(getTocEl()).toBeFalsy();
doPrepareTitleAndToc(EMPTY_DOC);
expect(getTocEl()).toBeFalsy();
});
it('should remove ToC a hard coded one', () => {
doPrepareTitleAndToc(DOC_WITH_EMBEDDED_TOC_WITHOUT_H1);
expect(getTocEl()).toBeFalsy();
doPrepareTitleAndToc(DOC_WITH_EMBEDDED_TOC_WITH_NO_TOC_H1);
expect(getTocEl()).toBeFalsy();
});
});
it('should not add a ToC element if there is no `<h1>` heading', () => {
doPrepareTitleAndToc(DOC_WITHOUT_H1);
expect(getTocEl()).toBeFalsy();
doPrepareTitleAndToc(EMPTY_DOC);
expect(getTocEl()).toBeFalsy();
});
it('should generate ToC entries if there is an `<h1>` heading', () => {
doAddTitleAndToc(DOC_WITH_H1, 'foo');

View File

@ -112,10 +112,15 @@ export class DocViewerComponent implements DoCheck, OnDestroy {
*/
protected prepareTitleAndToc(targetElem: HTMLElement, docId: string): () => void {
const titleEl = targetElem.querySelector('h1');
const hasToc = !!titleEl && !/no-?toc/i.test(titleEl.className);
const needsToc = !!titleEl && !/no-?toc/i.test(titleEl.className);
const embeddedToc = targetElem.querySelector('aio-toc.embedded');
if (hasToc) {
if (needsToc && !embeddedToc) {
// Add an embedded ToC if it's needed and there isn't one in the content already.
titleEl!.insertAdjacentHTML('afterend', '<aio-toc class="embedded"></aio-toc>');
} else if (!needsToc && embeddedToc) {
// Remove the embedded Toc if it's there and not needed.
embeddedToc.remove();
}
return () => {
@ -127,7 +132,7 @@ export class DocViewerComponent implements DoCheck, OnDestroy {
if (titleEl) {
title = (typeof titleEl.innerText === 'string') ? titleEl.innerText : titleEl.textContent;
if (hasToc) {
if (needsToc) {
this.tocService.genToc(targetElem, docId);
}
}