diff --git a/CHANGELOG-2.x.md b/CHANGELOG-2.x.md
index 87dc33e65b..4bf3aa575e 100644
--- a/CHANGELOG-2.x.md
+++ b/CHANGELOG-2.x.md
@@ -4,6 +4,7 @@
- Shorter chunk naming for pages. Instead of absolute path, we use relative path from site directory
- Use contenthash instead of chunkhash for better long term caching
+- Allow user to customize generated heading from MDX. Swizzle `@theme/Heading`
## 2.0.0-alpha.23
diff --git a/packages/docusaurus-mdx-loader/src/index.js b/packages/docusaurus-mdx-loader/src/index.js
index e2938db560..c276e52630 100644
--- a/packages/docusaurus-mdx-loader/src/index.js
+++ b/packages/docusaurus-mdx-loader/src/index.js
@@ -11,11 +11,10 @@ const emoji = require('remark-emoji');
const slug = require('remark-slug');
const matter = require('gray-matter');
const stringifyObject = require('stringify-object');
-const linkHeadings = require('./rehype/linkHeadings');
const rightToc = require('./remark/rightToc');
const DEFAULT_OPTIONS = {
- rehypePlugins: [linkHeadings],
+ rehypePlugins: [],
remarkPlugins: [emoji, slug, rightToc],
};
diff --git a/packages/docusaurus-mdx-loader/src/rehype/linkHeadings.js b/packages/docusaurus-mdx-loader/src/rehype/linkHeadings.js
deleted file mode 100644
index 9d2a668b95..0000000000
--- a/packages/docusaurus-mdx-loader/src/rehype/linkHeadings.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Copyright (c) 2017-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-const visit = require('unist-util-visit');
-
-const createAnchor = id => ({
- type: 'element',
- tagName: 'a',
- properties: {
- ariaHidden: true,
- className: 'anchor',
- id,
- },
-});
-
-const createLink = id => ({
- type: 'element',
- tagName: 'a',
- properties: {
- ariaHidden: true,
- className: 'hash-link',
- href: `#${id}`,
- },
- children: [
- {
- type: 'text',
- value: '#',
- },
- ],
-});
-
-const headings = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
-
-const visitor = node => {
- const {properties} = node;
- if (!properties || !properties.id || !headings.includes(node.tagName)) {
- return;
- }
-
- node.children.unshift(createLink(properties.id));
- node.children.unshift(createAnchor(properties.id));
-
- delete properties.id;
-};
-
-const transformer = node => {
- visit(node, 'element', visitor);
-};
-
-const plugin = () => transformer;
-
-module.exports = plugin;
diff --git a/packages/docusaurus-theme-classic/src/theme/Heading/index.js b/packages/docusaurus-theme-classic/src/theme/Heading/index.js
new file mode 100644
index 0000000000..789e637a27
--- /dev/null
+++ b/packages/docusaurus-theme-classic/src/theme/Heading/index.js
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2017-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/* eslint-disable jsx-a11y/anchor-has-content, jsx-a11y/anchor-is-valid */
+
+import React from 'react';
+
+import './styles.css';
+
+const Heading = Tag => ({id, ...props}) => (
+