Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(aio): fix window title for Home page #20440

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion aio/content/marketing/index.html
Expand Up @@ -25,7 +25,7 @@
<!-- MAIN CONTENT -->
<article>

<h1 class="no-toc" style="display: none"></h1>
<h1 class="no-anchor no-toc" style="display: none"></h1>

<div class="home-rows">

Expand Down
10 changes: 10 additions & 0 deletions aio/e2e/app.e2e-spec.ts
Expand Up @@ -15,6 +15,16 @@ describe('site App', function() {
expect(page.getDocViewerText()).toMatch(/Progressive web apps/i);
});

it('should set appropriate window titles', () => {
expect(browser.getTitle()).toBe('Angular');

page.getTopMenuLink('features').click();
expect(browser.getTitle()).toBe('Angular - FEATURES & BENEFITS');

page.homeLink.click();
expect(browser.getTitle()).toBe('Angular');
});

it('should show the tutorial index page at `/tutorial/` after jitterbugging through features', () => {
// check that we can navigate directly to the tutorial page
page.navigateTo('tutorial/');
Expand Down
1 change: 1 addition & 0 deletions aio/e2e/app.po.ts
Expand Up @@ -5,6 +5,7 @@ const githubRegex = /https:\/\/github.com\/angular\/angular\//;
export class SitePage {

links = element.all(by.css('md-toolbar a'));
homeLink = element(by.css('a.home'));
docsMenuLink = element(by.cssContainingText('aio-top-menu a', 'Docs'));
docViewer = element(by.css('aio-doc-viewer'));
codeExample = element.all(by.css('aio-doc-viewer pre > code'));
Expand Down
1 change: 0 additions & 1 deletion aio/package.json
Expand Up @@ -126,7 +126,6 @@
"lunr": "^2.1.0",
"protractor": "^5.2.0",
"rehype": "^4.0.0",
"rehype-autolink-headings": "^2.0.0",
"rehype-slug": "^2.0.0",
"remark": "^7.0.0",
"remark-html": "^6.0.0",
Expand Down
16 changes: 16 additions & 0 deletions aio/src/app/layout/doc-viewer/doc-viewer.component.spec.ts
Expand Up @@ -361,6 +361,22 @@ describe('DocViewerComponent', () => {
fixture.detectChanges();
expect(titleService.setTitle).toHaveBeenCalledWith('Angular - Text Content');
});

it('should still use `innerText` if available but empty', () => {
const querySelector_ = docViewerEl.querySelector;
spyOn(docViewerEl, 'querySelector').and.callFake((selector: string) => {
const elem = querySelector_.call(docViewerEl, selector);
Object.defineProperties(elem, {
innerText: { value: '' },
textContent: { value: 'Text Content' }
});
return elem;
});

setCurrentDoc('<h1><i style="visibility: hidden">link</i></h1>Some content');
fixture.detectChanges();
expect(titleService.setTitle).toHaveBeenCalledWith('Angular');
});
});

describe('TOC', () => {
Expand Down
6 changes: 4 additions & 2 deletions aio/src/app/layout/doc-viewer/doc-viewer.component.ts
Expand Up @@ -92,17 +92,19 @@ export class DocViewerComponent implements DoCheck, OnDestroy {

private addTitleAndToc(docId: string) {
this.tocService.reset();
let title = '';
const titleEl = this.hostElement.querySelector('h1');
let title = '';

// Only create TOC for docs with an <h1> title
// If you don't want a TOC, add "no-toc" class to <h1>
if (titleEl) {
title = (titleEl.innerText || titleEl.textContent).trim();
title = (typeof titleEl.innerText === 'string') ? titleEl.innerText : titleEl.textContent;
if (!/(no-toc|notoc)/i.test(titleEl.className)) {
this.tocService.genToc(this.hostElement, docId);
titleEl.insertAdjacentHTML('afterend', '<aio-toc class="embedded"></aio-toc>');
}
}

this.titleService.setTitle(title ? `Angular - ${title}` : 'Angular');
}

Expand Down
@@ -1,9 +1,34 @@
const has = require('hast-util-has-property');
const is = require('hast-util-is-element');
const slug = require('rehype-slug');
const link = require('rehype-autolink-headings');
const visit = require('unist-util-visit');

/**
* Get remark to inject anchors into headings
* Get remark to add IDs to headings and inject anchors into them.
* This is a stripped-down equivalent of [rehype-autolink-headings](https://github.com/wooorm/rehype-autolink-headings)
* that supports ignoring headings with the `no-anchor` class.
*/
const HEADINGS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
const NO_ANCHOR_CLASS = 'no-anchor';

const clone = obj => JSON.parse(JSON.stringify(obj));
const hasClass = (node, cls) => {
const className = node.properties.className;
return className && className.includes(cls);
};

const link = options =>
tree => visit(tree, node => {
if (is(node, HEADINGS) && has(node, 'id') && !hasClass(node, NO_ANCHOR_CLASS)) {
node.children.unshift({
type: 'element',
tagName: 'a',
properties: Object.assign(clone(options.properties), {href: `#${node.properties.id}`}),
children: clone(options.content)
});
}
});

module.exports = [
slug,
[link, {
Expand All @@ -12,11 +37,13 @@ module.exports = [
className: ['header-link'],
'aria-hidden': 'true'
},
content: {
type: 'element',
tagName: 'i',
properties: {className: ['material-icons']},
children: [{ type: 'text', value: 'link' }]
}
content: [
{
type: 'element',
tagName: 'i',
properties: {className: ['material-icons']},
children: [{ type: 'text', value: 'link' }]
}
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should content be an array? Was this a mistake in the original on my part?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see that in woorm's version he wraps the content in an array.

}]
];
Expand Up @@ -14,20 +14,37 @@ describe('autolink-headings postprocessor', () => {
});

it('should add anchors to headings', () => {
const docs = [ {
docType: 'a',
renderedContent: `
<h1>Heading 1</h2>
<h2>Heading with <strong>bold</strong></h2>
<h3>Heading with encoded chars &#x26;</h3>
`
}];
const originalContent = `
<h1>Heading 1</h2>
<h2>Heading with <strong>bold</strong></h2>
<h3>Heading with encoded chars &#x26;</h3>
`;
const processedContent = `
<h1 id="heading-1"><a title="Link to this heading" class="header-link" aria-hidden="true" href="#heading-1"><i class="material-icons">link</i></a>Heading 1</h1>
<h2 id="heading-with-bold"><a title="Link to this heading" class="header-link" aria-hidden="true" href="#heading-with-bold"><i class="material-icons">link</i></a>Heading with <strong>bold</strong></h2>
<h3 id="heading-with-encoded-chars-"><a title="Link to this heading" class="header-link" aria-hidden="true" href="#heading-with-encoded-chars-"><i class="material-icons">link</i></a>Heading with encoded chars &#x26;</h3>
`;

const docs = [{docType: 'a', renderedContent: originalContent}];
processor.$process(docs);
expect(docs[0].renderedContent).toBe(processedContent);
});

it('should ignore headings with the `no-anchor` class', () => {
const originalContent = `
<h1 class="no-anchor">Heading 1</h2>
<h2 class="no-anchor">Heading with <strong>bold</strong></h2>
<h3 class="no-anchor">Heading with encoded chars &#x26;</h3>
`;
const processedContent = `
<h1 class="no-anchor" id="heading-1">Heading 1</h1>
<h2 class="no-anchor" id="heading-with-bold">Heading with <strong>bold</strong></h2>
<h3 class="no-anchor" id="heading-with-encoded-chars-">Heading with encoded chars &#x26;</h3>
`;

const docs = [{docType: 'a', renderedContent: originalContent}];
processor.$process(docs);
expect(docs[0].renderedContent).toEqual(`
<h1 id="heading-1"><a title="Link to this heading" class="header-link" aria-hidden="true" href="#heading-1"><i class="material-icons">link</i></a>Heading 1</h1>
<h2 id="heading-with-bold"><a title="Link to this heading" class="header-link" aria-hidden="true" href="#heading-with-bold"><i class="material-icons">link</i></a>Heading with <strong>bold</strong></h2>
<h3 id="heading-with-encoded-chars-"><a title="Link to this heading" class="header-link" aria-hidden="true" href="#heading-with-encoded-chars-"><i class="material-icons">link</i></a>Heading with encoded chars &#x26;</h3>
`);
expect(docs[0].renderedContent).toBe(processedContent);
});
});

11 changes: 1 addition & 10 deletions aio/yarn.lock
Expand Up @@ -2977,7 +2977,7 @@ express@^4.13.3:
utils-merge "1.0.1"
vary "~1.1.2"

extend@3, extend@^3.0.0, extend@^3.0.1, extend@~3.0.0, extend@~3.0.1:
extend@3, extend@^3.0.0, extend@~3.0.0, extend@~3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"

Expand Down Expand Up @@ -6999,15 +6999,6 @@ regjsparser@^0.1.4:
dependencies:
jsesc "~0.5.0"

rehype-autolink-headings@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/rehype-autolink-headings/-/rehype-autolink-headings-2.0.2.tgz#48c7161b1a1020e942c758eb6b2c55cb1bc504d0"
dependencies:
extend "^3.0.1"
hast-util-has-property "^1.0.0"
hast-util-is-element "^1.0.0"
unist-util-visit "^1.1.0"

rehype-parse@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-3.1.0.tgz#7f5227a597a3f39fc4b938646161539c444ee728"
Expand Down