feat(aio): add GH-style anchor links to headings (#16161)
Closes #16126 PR Close #16161
This commit is contained in:
		
							parent
							
								
									1bfa7c6f14
								
							
						
					
					
						commit
						1e848d696b
					
				@ -81,7 +81,9 @@
 | 
			
		||||
    "lodash": "^4.17.4",
 | 
			
		||||
    "protractor": "~5.1.0",
 | 
			
		||||
    "remark": "^7.0.0",
 | 
			
		||||
    "remark-autolink-headings": "^4.0.0",
 | 
			
		||||
    "remark-html": "^6.0.0",
 | 
			
		||||
    "remark-slug": "^4.2.2",
 | 
			
		||||
    "rho": "https://github.com/petebacondarwin/rho#master",
 | 
			
		||||
    "rimraf": "^2.6.1",
 | 
			
		||||
    "shelljs": "^0.7.7",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										42
									
								
								aio/src/styles/2-modules/_heading-anchors.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								aio/src/styles/2-modules/_heading-anchors.scss
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
			
		||||
h1, h2, h3, h4, h5, h6 {
 | 
			
		||||
  .icon-link {
 | 
			
		||||
    color: $darkgray;
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
    visibility: hidden;
 | 
			
		||||
    margin: 8px;
 | 
			
		||||
 | 
			
		||||
    font: normal normal 24px 'Material Icons';
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    line-height: 1;
 | 
			
		||||
    text-transform: none;
 | 
			
		||||
    letter-spacing: normal;
 | 
			
		||||
    word-wrap: normal;
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
    direction: ltr;
 | 
			
		||||
 | 
			
		||||
    /* Support for all WebKit browsers. */
 | 
			
		||||
    -webkit-font-smoothing: antialiased;
 | 
			
		||||
    /* Support for Safari and Chrome. */
 | 
			
		||||
    text-rendering: optimizeLegibility;
 | 
			
		||||
 | 
			
		||||
    /* Support for Firefox. */
 | 
			
		||||
    -moz-osx-font-smoothing: grayscale;
 | 
			
		||||
 | 
			
		||||
    /* Support for IE. */
 | 
			
		||||
    font-feature-settings: 'liga';
 | 
			
		||||
 | 
			
		||||
    &:before { content: 'link'; }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  a {
 | 
			
		||||
    text-decoration: none;
 | 
			
		||||
    padding-left: 8px;
 | 
			
		||||
    margin-left: -30px;
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &:hover .icon-link {
 | 
			
		||||
    visibility: visible
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -24,3 +24,4 @@
 | 
			
		||||
   @import 'callout';
 | 
			
		||||
   @import 'resources';
 | 
			
		||||
   @import 'edit-page-cta';
 | 
			
		||||
   @import 'heading-anchors';
 | 
			
		||||
@ -12,7 +12,7 @@ module.exports = function fixInternalDocumentLinks() {
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    $runAfter: ['inlineTagProcessor'],
 | 
			
		||||
    $runBefore: ['writeFilesProcessor'],
 | 
			
		||||
    $runBefore: ['convertToJsonProcessor'],
 | 
			
		||||
    $process: function(docs) {
 | 
			
		||||
      docs.forEach(doc => {
 | 
			
		||||
        doc.renderedContent = doc.renderedContent.replace(INTERNAL_LINK, (_, pre, hash) => {
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,7 @@ describe('fixInternalDocumentLinks processor', () => {
 | 
			
		||||
 | 
			
		||||
  it('should run before the correct processor', () => {
 | 
			
		||||
    const processor = processorFactory();
 | 
			
		||||
    expect(processor.$runBefore).toEqual(['writeFilesProcessor']);
 | 
			
		||||
    expect(processor.$runBefore).toEqual(['convertToJsonProcessor']);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should run after the correct processor', () => {
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,6 @@
 | 
			
		||||
const remark = require('remark');
 | 
			
		||||
const slug = require('remark-slug');
 | 
			
		||||
const autolinkHeadings = require('remark-autolink-headings');
 | 
			
		||||
const html = require('remark-html');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -15,6 +17,8 @@ module.exports = function renderMarkdown() {
 | 
			
		||||
                    // .use(() => tree => {
 | 
			
		||||
                    //   console.log(require('util').inspect(tree, { colors: true, depth: 4 }));
 | 
			
		||||
                    // })
 | 
			
		||||
                    .use(slug)
 | 
			
		||||
                    .use(autolinkHeadings)
 | 
			
		||||
                    .use(html);
 | 
			
		||||
 | 
			
		||||
  return function renderMarkdownImpl(content) {
 | 
			
		||||
 | 
			
		||||
@ -16,7 +16,7 @@ describe('remark: renderMarkdown service', () => {
 | 
			
		||||
    const output = renderMarkdown(content);
 | 
			
		||||
 | 
			
		||||
    expect(output).toEqual(
 | 
			
		||||
        '<h1>heading 1</h1>\n' +
 | 
			
		||||
        '<h1 id="heading-1"><a href="#heading-1" aria-hidden="true"><span class="icon icon-link"></span></a>heading 1</h1>\n' +
 | 
			
		||||
        '<p>A paragraph with <strong>bold</strong> and <em>italic</em>.</p>\n' +
 | 
			
		||||
        '<ul>\n' +
 | 
			
		||||
        '<li>List item 1</li>\n' +
 | 
			
		||||
@ -25,9 +25,9 @@ describe('remark: renderMarkdown service', () => {
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should not process markdown inside inline tags', () => {
 | 
			
		||||
    const content = '# heading {@link some_url_path}';
 | 
			
		||||
    const content = '* list item {@link some_url_path}';
 | 
			
		||||
    const output = renderMarkdown(content);
 | 
			
		||||
    expect(output).toEqual('<h1>heading {@link some_url_path}</h1>\n');
 | 
			
		||||
    expect(output).toEqual('<ul>\n<li>list item {@link some_url_path}</li>\n</ul>\n');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should not put block level inline tags inside paragraphs', () => {
 | 
			
		||||
@ -67,4 +67,14 @@ describe('remark: renderMarkdown service', () => {
 | 
			
		||||
    const output = renderMarkdown(content);
 | 
			
		||||
    expect(output).toEqual('<p>some text</p>\n<p>    indented text</p>\n<p>other text</p>\n');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should add id slugs and links to headings', () => {
 | 
			
		||||
    const content = '# heading 1\n\nSome text\n\n## heading 2\n\nMore text';
 | 
			
		||||
    const output = renderMarkdown(content);
 | 
			
		||||
    expect(output).toEqual(
 | 
			
		||||
      '<h1 id="heading-1"><a href="#heading-1" aria-hidden="true"><span class="icon icon-link"></span></a>heading 1</h1>\n' +
 | 
			
		||||
      '<p>Some text</p>\n' +
 | 
			
		||||
      '<h2 id="heading-2"><a href="#heading-2" aria-hidden="true"><span class="icon icon-link"></span></a>heading 2</h2>\n' +
 | 
			
		||||
      '<p>More text</p>\n');
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@ -2024,6 +2024,10 @@ ember-cli-string-utils@^1.0.0:
 | 
			
		||||
  version "1.1.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/ember-cli-string-utils/-/ember-cli-string-utils-1.1.0.tgz#39b677fc2805f55173735376fcef278eaa4452a1"
 | 
			
		||||
 | 
			
		||||
emoji-regex@^6.0.0:
 | 
			
		||||
  version "6.4.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.4.2.tgz#a30b6fee353d406d96cfb9fa765bdc82897eff6e"
 | 
			
		||||
 | 
			
		||||
emojis-list@^2.0.0:
 | 
			
		||||
  version "2.1.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
 | 
			
		||||
@ -2766,6 +2770,12 @@ getpass@^0.1.1:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    assert-plus "^1.0.0"
 | 
			
		||||
 | 
			
		||||
github-slugger@^1.0.0:
 | 
			
		||||
  version "1.1.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.1.1.tgz#5444671f65e5a5a424cfa8ba3255cc1f7baf07ea"
 | 
			
		||||
  dependencies:
 | 
			
		||||
    emoji-regex "^6.0.0"
 | 
			
		||||
 | 
			
		||||
gl-matrix@2.3.2:
 | 
			
		||||
  version "2.3.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-2.3.2.tgz#aac808c74af7d5db05fe04cb60ca1a0fcb174d74"
 | 
			
		||||
@ -4285,6 +4295,10 @@ mdast-util-to-hast@^2.1.1:
 | 
			
		||||
    unist-util-visit "^1.1.0"
 | 
			
		||||
    xtend "^4.0.1"
 | 
			
		||||
 | 
			
		||||
mdast-util-to-string@^1.0.0:
 | 
			
		||||
  version "1.0.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-1.0.2.tgz#dc996a24d2b521178d3fac3993680c03a683e1dd"
 | 
			
		||||
 | 
			
		||||
media-typer@0.3.0:
 | 
			
		||||
  version "0.3.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
 | 
			
		||||
@ -5605,6 +5619,12 @@ relateurl@0.2.x:
 | 
			
		||||
  version "0.2.7"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
 | 
			
		||||
 | 
			
		||||
remark-autolink-headings@^4.0.0:
 | 
			
		||||
  version "4.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/remark-autolink-headings/-/remark-autolink-headings-4.0.0.tgz#1edabab6636e8cb26a36bf4c06caaec28355d3fc"
 | 
			
		||||
  dependencies:
 | 
			
		||||
    unist-util-visit "^1.0.1"
 | 
			
		||||
 | 
			
		||||
remark-html@^6.0.0:
 | 
			
		||||
  version "6.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/remark-html/-/remark-html-6.0.0.tgz#ade7d94b60e452158f28615218450682601dbfc1"
 | 
			
		||||
@ -5635,6 +5655,14 @@ remark-parse@^3.0.0:
 | 
			
		||||
    vfile-location "^2.0.0"
 | 
			
		||||
    xtend "^4.0.1"
 | 
			
		||||
 | 
			
		||||
remark-slug@^4.2.2:
 | 
			
		||||
  version "4.2.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/remark-slug/-/remark-slug-4.2.2.tgz#3cfaa02e2e24d98405b296072f2ebbdfad279eb6"
 | 
			
		||||
  dependencies:
 | 
			
		||||
    github-slugger "^1.0.0"
 | 
			
		||||
    mdast-util-to-string "^1.0.0"
 | 
			
		||||
    unist-util-visit "^1.0.0"
 | 
			
		||||
 | 
			
		||||
remark-stringify@^3.0.0:
 | 
			
		||||
  version "3.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-3.0.0.tgz#f1720893a3e7c845824d95bb573d628d1346ba2a"
 | 
			
		||||
@ -6915,7 +6943,7 @@ unist-util-stringify-position@^1.0.0:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    has "^1.0.1"
 | 
			
		||||
 | 
			
		||||
unist-util-visit@^1.0.0, unist-util-visit@^1.1.0:
 | 
			
		||||
unist-util-visit@^1.0.0, unist-util-visit@^1.0.1, unist-util-visit@^1.1.0:
 | 
			
		||||
  version "1.1.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.1.1.tgz#e917a3b137658b335cb4420c7da2e74d928e4e94"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user