diff --git a/aio/package.json b/aio/package.json index a72ee642ae..f560a34c89 100644 --- a/aio/package.json +++ b/aio/package.json @@ -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", diff --git a/aio/src/styles/2-modules/_heading-anchors.scss b/aio/src/styles/2-modules/_heading-anchors.scss new file mode 100644 index 0000000000..e186bcc21a --- /dev/null +++ b/aio/src/styles/2-modules/_heading-anchors.scss @@ -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 + } +} \ No newline at end of file diff --git a/aio/src/styles/2-modules/_modules-dir.scss b/aio/src/styles/2-modules/_modules-dir.scss index 09dfe3f2d1..04779aab5e 100644 --- a/aio/src/styles/2-modules/_modules-dir.scss +++ b/aio/src/styles/2-modules/_modules-dir.scss @@ -23,4 +23,5 @@ @import 'scrollbar'; @import 'callout'; @import 'resources'; - @import 'edit-page-cta'; \ No newline at end of file + @import 'edit-page-cta'; + @import 'heading-anchors'; \ No newline at end of file diff --git a/aio/tools/transforms/angular.io-package/processors/fixInternalDocumentLinks.js b/aio/tools/transforms/angular.io-package/processors/fixInternalDocumentLinks.js index ed12787a52..0ed3b3bade 100644 --- a/aio/tools/transforms/angular.io-package/processors/fixInternalDocumentLinks.js +++ b/aio/tools/transforms/angular.io-package/processors/fixInternalDocumentLinks.js @@ -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) => { diff --git a/aio/tools/transforms/angular.io-package/processors/fixInternalDocumentLinks.spec.js b/aio/tools/transforms/angular.io-package/processors/fixInternalDocumentLinks.spec.js index b2d6802466..138198ce41 100644 --- a/aio/tools/transforms/angular.io-package/processors/fixInternalDocumentLinks.spec.js +++ b/aio/tools/transforms/angular.io-package/processors/fixInternalDocumentLinks.spec.js @@ -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', () => { diff --git a/aio/tools/transforms/remark-package/services/renderMarkdown.js b/aio/tools/transforms/remark-package/services/renderMarkdown.js index 3e9b0bc2eb..acfa9ab4f8 100644 --- a/aio/tools/transforms/remark-package/services/renderMarkdown.js +++ b/aio/tools/transforms/remark-package/services/renderMarkdown.js @@ -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) { diff --git a/aio/tools/transforms/remark-package/services/renderMarkdown.spec.js b/aio/tools/transforms/remark-package/services/renderMarkdown.spec.js index 3bb1b9352c..c74e9573a6 100644 --- a/aio/tools/transforms/remark-package/services/renderMarkdown.spec.js +++ b/aio/tools/transforms/remark-package/services/renderMarkdown.spec.js @@ -16,7 +16,7 @@ describe('remark: renderMarkdown service', () => { const output = renderMarkdown(content); expect(output).toEqual( - '
A paragraph with bold and italic.
\n' + 'some text
\nindented text
\nother text
\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( + 'Some text
\n' + + 'More text
\n'); + }); }); diff --git a/aio/yarn.lock b/aio/yarn.lock index a147622831..1c50220272 100644 --- a/aio/yarn.lock +++ b/aio/yarn.lock @@ -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"