diff --git a/css/tailwind.css b/css/tailwind.css index b7d9ce9..64246d0 100644 --- a/css/tailwind.css +++ b/css/tailwind.css @@ -14,6 +14,19 @@ @apply hidden; } +.code-line { + @apply pl-4 -mx-4 border-l-4 border-gray-800; +} + +.highlight-line { + @apply -mx-4 bg-gray-700 bg-opacity-50 border-l-4 border-primary-500; +} + +.line-number::before { + @apply pr-4 -ml-2 text-gray-400; + content: attr(line); +} + html { scroll-behavior: smooth; } diff --git a/data/blog/new-features-in-v1.mdx b/data/blog/new-features-in-v1.mdx index fb48d70..2e43d0b 100644 --- a/data/blog/new-features-in-v1.mdx +++ b/data/blog/new-features-in-v1.mdx @@ -1,6 +1,6 @@ --- title: 'New features in v1' -date: '2021-06-02' +date: '2021-06-29' tags: ['next-js', 'tailwind', 'guide'] draft: false summary: 'An overview of the new features released in v1 - code block copy, multiple authors, frontmatter layout and more' @@ -12,15 +12,17 @@ layout: PostSimple A post on the new features introduced in v1.0. New features: - [Theme colors](#theme-colors) +- [Xdm MDX compiler](#xdm-mdx-compiler) - [Layouts](#layouts) - [Multiple authors](#multiple-authors) - [Copy button for code blocks](#copy-button-for-code-blocks) +- [Line highlighting and line numbers](#line-highlighting-and-line-numbers) ## Theme colors You can easily modify the theme color by changing the primary attribute in the tailwind config file: -```:tailwind.config.js +```js:tailwind.config.js theme: { colors: { primary: colors.teal, @@ -37,6 +39,18 @@ Tailwind includes great default color palettes that can be used for theming your Migrating from v1? You can revert to the previous theme by setting `primary` to `colors.sky` (Tailwind 2.2.2 and above, otherwise `colors.lightBlue`) and changing gray to `colors.coolGray`. +## Xdm MDX compiler + +We switch the MDX bundler from [next-mdx-remote](https://github.com/hashicorp/next-mdx-remote) to [mdx-bundler](https://github.com/kentcdodds/mdx-bundler). +This uses [xdm](https://github.com/wooorm/xdm) under the hood uses the latest micromark 3 and remark, rehype libraries. + +**Warning:** If you were using custom remark or rehype libraries, please upgrade to micromark 3 compatible ones. If you are upgrading, please delete `node_modules` and `package-lock.json` to avoid having past dependencies related issues. + +[xdm](https://github.com/wooorm/xdm) contains multiple improvements over [@mdx-js/mdx](https://github.com/mdx-js/mdx), the compiler used internally by next-mdx-remote, but there might be some breaking behaviour changes. +Please check your markdown output to verify. + +Some new possibilities include loading components directly in the mdx file using the import syntax and including js code which could be compiled at the build step. + ## Layouts You can map mdx blog content to layout components by configuring the frontmatter field. For example, this post is written with the new `PostSimple` layout! @@ -110,7 +124,7 @@ Information on authors is now split from `siteMetadata.json` and stored in its o Here's how an author markdown file might looks like: -```:default.md +```md:default.md --- name: Tails Azimuth avatar: /static/images/avatar.png @@ -153,3 +167,46 @@ A demo of a multiple author post is shown in the [Introducing Tailwind Nextjs St Hover over a code block and you will notice a Github inspired copy button! You can modify `./components/Pre.js` to further customise it. The component is passed to `MDXComponents` and modifies all `
` blocks.
+
+## Line highlighting and line numbers
+
+Line highlighting and line numbers is now supported out of the box thanks to the new [rehype-prism-plus plugin](https://github.com/timlrx/rehype-prism-plus)
+
+The following javascript code block:
+
+````
+```js {1, 3-4} showLineNumbers
+var num1, num2, sum
+num1 = prompt('Enter first number')
+num2 = prompt('Enter second number')
+sum = parseInt(num1) + parseInt(num2) // "+" means "add"
+alert('Sum = ' + sum) // "+" means combine into a string
+```
+````
+
+will appear as:
+
+```js {1,3-4} showLineNumbers
+var num1, num2, sum
+num1 = prompt('Enter first number')
+num2 = prompt('Enter second number')
+sum = parseInt(num1) + parseInt(num2) // "+" means "add"
+alert('Sum = ' + sum) // "+" means combine into a string
+```
+
+To modify the styles, change the following class selectors in the `tailwind.css` file:
+
+```css
+.code-line {
+  @apply pl-4 -mx-4 border-l-4 border-gray-800;
+}
+
+.highlight-line {
+  @apply -mx-4 bg-gray-700 bg-opacity-50 border-l-4 border-primary-500;
+}
+
+.line-number::before {
+  @apply pr-4 -ml-2 text-gray-400;
+  content: attr(line);
+}
+```
diff --git a/lib/mdx.js b/lib/mdx.js
index 3df137c..bf8f4dc 100644
--- a/lib/mdx.js
+++ b/lib/mdx.js
@@ -86,7 +86,7 @@ export async function getFileBySlug(type, slug) {
       options.rehypePlugins = [
         ...(options.rehypePlugins ?? []),
         require('rehype-katex'),
-        require('@mapbox/rehype-prism'),
+        [require('rehype-prism-plus'), { ignoreMissing: true }],
         () => {
           return (tree) => {
             visit(tree, 'element', (node, index, parent) => {
diff --git a/lib/remark-code-title.js b/lib/remark-code-title.js
index ed7d785..0c7e9ef 100644
--- a/lib/remark-code-title.js
+++ b/lib/remark-code-title.js
@@ -4,8 +4,8 @@ module.exports = function (options) {
   return (tree) =>
     visit(tree, 'code', (node, index) => {
       const nodeLang = node.lang || ''
-      let language = '',
-        title = ''
+      let language = ''
+      let title = ''
 
       if (nodeLang.includes(':')) {
         language = nodeLang.slice(0, nodeLang.search(':'))
diff --git a/package-lock.json b/package-lock.json
index 24d80e9..3d66991 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1545,16 +1545,6 @@
       "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz",
       "integrity": "sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug=="
     },
-    "@mapbox/rehype-prism": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/@mapbox/rehype-prism/-/rehype-prism-0.6.0.tgz",
-      "integrity": "sha512-/0Ev/PB4fXdKPT6VDzVpnAPxGpWFIc4Yz3mf/DzLEMxlpIPZpZlCzaFk4V4NGFofQXPc41+GpEcZtWP3VuFWVA==",
-      "requires": {
-        "hast-util-to-string": "^1.0.4",
-        "refractor": "^3.3.1",
-        "unist-util-visit": "^2.0.3"
-      }
-    },
     "@next/bundle-analyzer": {
       "version": "11.0.1",
       "resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-11.0.1.tgz",
@@ -1931,6 +1921,11 @@
       "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz",
       "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw=="
     },
+    "@types/prismjs": {
+      "version": "1.16.5",
+      "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.16.5.tgz",
+      "integrity": "sha512-nSU7U6FQDJJCraFNwaHmH5YDsd/VA9rTnJ7B7AGFdn+m+VSt3FjLWN7+AbqxZ67dbFazqtrDFUto3HK4ljrHIg=="
+    },
     "@types/q": {
       "version": "1.5.4",
       "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
@@ -2791,17 +2786,6 @@
         }
       }
     },
-    "clipboard": {
-      "version": "2.0.8",
-      "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.8.tgz",
-      "integrity": "sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==",
-      "optional": true,
-      "requires": {
-        "good-listener": "^1.2.2",
-        "select": "^1.1.2",
-        "tiny-emitter": "^2.0.0"
-      }
-    },
     "coa": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz",
@@ -3201,12 +3185,6 @@
       "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
       "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM="
     },
-    "delegate": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
-      "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
-      "optional": true
-    },
     "depd": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -4495,15 +4473,6 @@
         }
       }
     },
-    "good-listener": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
-      "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
-      "optional": true,
-      "requires": {
-        "delegate": "^3.1.2"
-      }
-    },
     "graceful-fs": {
       "version": "4.2.6",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
@@ -6730,6 +6699,11 @@
         "lines-and-columns": "^1.1.6"
       }
     },
+    "parse-numeric-range": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.2.0.tgz",
+      "integrity": "sha512-1q2tXpAOplPxcl8vrIGPWz1dJxxfmdRkCFcpxxMBerDnGuuHalOWF/xj9L8Nn5XoTUoB/6F0CeQBp2fMgkOYFg=="
+    },
     "parse5": {
       "version": "6.0.1",
       "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
@@ -6982,14 +6956,6 @@
       "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
       "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE="
     },
-    "prismjs": {
-      "version": "1.23.0",
-      "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz",
-      "integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==",
-      "requires": {
-        "clipboard": "^2.0.0"
-      }
-    },
     "process": {
       "version": "0.11.10",
       "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
@@ -7312,16 +7278,6 @@
         }
       }
     },
-    "refractor": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.3.1.tgz",
-      "integrity": "sha512-vaN6R56kLMuBszHSWlwTpcZ8KTMG6aUCok4GrxYDT20UIOXxOc5o6oDc8tNTzSlH3m2sI+Eu9Jo2kVdDcUTWYw==",
-      "requires": {
-        "hastscript": "^6.0.0",
-        "parse-entities": "^2.0.0",
-        "prismjs": "~1.23.0"
-      }
-    },
     "regenerate": {
       "version": "1.4.2",
       "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@@ -7437,6 +7393,147 @@
         "parse5": "^6.0.0"
       }
     },
+    "rehype-prism-plus": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/rehype-prism-plus/-/rehype-prism-plus-0.0.1.tgz",
+      "integrity": "sha512-tq9PtqEVEATTNDIV22b/3foSqM0nGS5akAImavIwGKnswFrBoFjTHowOwIvermb1B4tx1hjDtD0i2HOHITUg3g==",
+      "requires": {
+        "hast-util-to-string": "^1.0.4",
+        "parse-numeric-range": "^1.2.0",
+        "refractor": "^4.0.0",
+        "unist-util-visit": "^3.1.0"
+      },
+      "dependencies": {
+        "character-entities": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.0.tgz",
+          "integrity": "sha512-oHqMj3eAuJ77/P5PaIRcqk+C3hdfNwyCD2DAUcD5gyXkegAuF2USC40CEqPscDk4I8FRGMTojGJQkXDsN5QlJA=="
+        },
+        "character-entities-legacy": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-2.0.0.tgz",
+          "integrity": "sha512-YwaEtEvWLpFa6Wh3uVLrvirA/ahr9fki/NUd/Bd4OR6EdJ8D22hovYQEOUCBfQfcqnC4IAMGMsHXY1eXgL4ZZA=="
+        },
+        "character-reference-invalid": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.0.tgz",
+          "integrity": "sha512-pE3Z15lLRxDzWJy7bBHBopRwfI20sbrMVLQTC7xsPglCHf4Wv1e167OgYAFP78co2XlhojDyAqA+IAJse27//g=="
+        },
+        "comma-separated-tokens": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.2.tgz",
+          "integrity": "sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg=="
+        },
+        "hast-util-parse-selector": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.0.tgz",
+          "integrity": "sha512-AyjlI2pTAZEOeu7GeBPZhROx0RHBnydkQIXlhnFzDi0qfXTmGUWoCYZtomHbrdrheV4VFUlPcfJ6LMF5T6sQzg==",
+          "requires": {
+            "@types/hast": "^2.0.0"
+          }
+        },
+        "hastscript": {
+          "version": "7.0.1",
+          "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.0.1.tgz",
+          "integrity": "sha512-3Nww02NdnAoLZlI4mifLRYU9jZ1PrMD+eYnnW3RGVKlRD2bW+fNTvr1KLnET/DAf8c6CMlMblXVUhXJiGIKwDA==",
+          "requires": {
+            "@types/hast": "^2.0.0",
+            "comma-separated-tokens": "^2.0.0",
+            "hast-util-parse-selector": "^3.0.0",
+            "property-information": "^6.0.0",
+            "space-separated-tokens": "^2.0.0"
+          }
+        },
+        "is-alphabetical": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.0.tgz",
+          "integrity": "sha512-5OV8Toyq3oh4eq6sbWTYzlGdnMT/DPI5I0zxUBxjiigQsZycpkKF3kskkao3JyYGuYDHvhgJF+DrjMQp9SX86w=="
+        },
+        "is-alphanumerical": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.0.tgz",
+          "integrity": "sha512-t+2GlJ+hO9yagJ+jU3+HSh80VKvz/3cG2cxbGGm4S0hjKuhWQXgPVUVOZz3tqZzMjhmphZ+1TIJTlRZRoe6GCQ==",
+          "requires": {
+            "is-alphabetical": "^2.0.0",
+            "is-decimal": "^2.0.0"
+          }
+        },
+        "is-decimal": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.0.tgz",
+          "integrity": "sha512-QfrfjQV0LjoWQ1K1XSoEZkTAzSa14RKVMa5zg3SdAfzEmQzRM4+tbSFWb78creCeA9rNBzaZal92opi1TwPWZw=="
+        },
+        "is-hexadecimal": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.0.tgz",
+          "integrity": "sha512-vGOtYkiaxwIiR0+Ng/zNId+ZZehGfINwTzdrDqc6iubbnQWhnPuYymOzOKUDqa2cSl59yHnEh2h6MvRLQsyNug=="
+        },
+        "parse-entities": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-3.0.0.tgz",
+          "integrity": "sha512-AJlcIFDNPEP33KyJLguv0xJc83BNvjxwpuUIcetyXUsLpVXAUCePJ5kIoYtEN2R1ac0cYaRu/vk9dVFkewHQhQ==",
+          "requires": {
+            "character-entities": "^2.0.0",
+            "character-entities-legacy": "^2.0.0",
+            "character-reference-invalid": "^2.0.0",
+            "is-alphanumerical": "^2.0.0",
+            "is-decimal": "^2.0.0",
+            "is-hexadecimal": "^2.0.0"
+          }
+        },
+        "prismjs": {
+          "version": "1.24.0",
+          "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.24.0.tgz",
+          "integrity": "sha512-SqV5GRsNqnzCL8k5dfAjCNhUrF3pR0A9lTDSCUZeh/LIshheXJEaP0hwLz2t4XHivd2J/v2HR+gRnigzeKe3cQ=="
+        },
+        "property-information": {
+          "version": "6.0.1",
+          "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.0.1.tgz",
+          "integrity": "sha512-F4WUUAF7fMeF4/JUFHNBWDaKDXi2jbvqBW/y6o5wsf3j19wTZ7S60TmtB5HoBhtgw7NKQRMWuz5vk2PR0CygUg=="
+        },
+        "refractor": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/refractor/-/refractor-4.1.0.tgz",
+          "integrity": "sha512-qUcwf/qkP3sH7RrhgEPt5d4/5M7lK9nCH8UkYXNsmXMDUd7JqGg91IQVEUS9maJqqiF4Bo02P5ozWSXOQb7jow==",
+          "requires": {
+            "@types/hast": "^2.0.0",
+            "@types/prismjs": "^1.0.0",
+            "hastscript": "^7.0.0",
+            "parse-entities": "^3.0.0",
+            "prismjs": "~1.24.0"
+          }
+        },
+        "space-separated-tokens": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.1.tgz",
+          "integrity": "sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw=="
+        },
+        "unist-util-is": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.1.0.tgz",
+          "integrity": "sha512-pWspZ+AvTqYbC+xWeRmzGqbcY8Na08Eowlfs2xchWTYot8vBBAq+syrE/LWS0bw1D/JOu4lwzDbEb6Mz13tK+g=="
+        },
+        "unist-util-visit": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-3.1.0.tgz",
+          "integrity": "sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA==",
+          "requires": {
+            "@types/unist": "^2.0.0",
+            "unist-util-is": "^5.0.0",
+            "unist-util-visit-parents": "^4.0.0"
+          }
+        },
+        "unist-util-visit-parents": {
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz",
+          "integrity": "sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==",
+          "requires": {
+            "@types/unist": "^2.0.0",
+            "unist-util-is": "^5.0.0"
+          }
+        }
+      }
+    },
     "rehype-stringify": {
       "version": "8.0.0",
       "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-8.0.0.tgz",
@@ -7679,12 +7776,6 @@
         "kind-of": "^6.0.0"
       }
     },
-    "select": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
-      "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=",
-      "optional": true
-    },
     "semver": {
       "version": "6.3.0",
       "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -8400,12 +8491,6 @@
         "setimmediate": "^1.0.4"
       }
     },
-    "tiny-emitter": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
-      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
-      "optional": true
-    },
     "tmp": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
diff --git a/package.json b/package.json
index 29135a9..f288adc 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,6 @@
     "prepare": "husky install"
   },
   "dependencies": {
-    "@mapbox/rehype-prism": "^0.6.0",
     "@tailwindcss/forms": "^0.3.2",
     "@tailwindcss/typography": "^0.4.0",
     "autoprefixer": "^10.2.5",
@@ -27,6 +26,7 @@
     "react-dom": "17.0.2",
     "reading-time": "1.3.0",
     "rehype-katex": "^5.0.0",
+    "rehype-prism-plus": "0.0.1",
     "remark-autolink-headings": "6.0.1",
     "remark-footnotes": "^3.0.0",
     "remark-gfm": "^1.0.0",