upstream #1
@ -1,5 +1,5 @@
|
|||||||
import Image from 'next/image'
|
import Image from './Image'
|
||||||
import Link from '@/components/Link'
|
import Link from './Link'
|
||||||
|
|
||||||
const Card = ({ title, description, imgSrc, href }) => (
|
const Card = ({ title, description, imgSrc, href }) => (
|
||||||
<div className="p-4 md:w-1/2 md" style={{ maxWidth: '544px' }}>
|
<div className="p-4 md:w-1/2 md" style={{ maxWidth: '544px' }}>
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { MDXRemote } from 'next-mdx-remote'
|
/* eslint-disable react/display-name */
|
||||||
|
import { useMemo } from 'react'
|
||||||
|
import { getMDXComponent } from 'mdx-bundler/client'
|
||||||
import Image from './Image'
|
import Image from './Image'
|
||||||
import CustomLink from './Link'
|
import CustomLink from './Link'
|
||||||
import Pre from './Pre'
|
import Pre from './Pre'
|
||||||
@ -7,14 +9,14 @@ export const MDXComponents = {
|
|||||||
Image,
|
Image,
|
||||||
a: CustomLink,
|
a: CustomLink,
|
||||||
pre: Pre,
|
pre: Pre,
|
||||||
|
wrapper: ({ components, layout, ...rest }) => {
|
||||||
|
const Layout = require(`../layouts/${layout}`).default
|
||||||
|
return <Layout {...rest} />
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MDXLayoutRenderer = ({ layout, mdxSource, ...rest }) => {
|
export const MDXLayoutRenderer = ({ layout, mdxSource, ...rest }) => {
|
||||||
const LayoutComponent = require(`../layouts/${layout}`).default
|
const MDXLayout = useMemo(() => getMDXComponent(mdxSource), [mdxSource])
|
||||||
|
|
||||||
return (
|
return <MDXLayout layout={layout} components={MDXComponents} {...rest} />
|
||||||
<LayoutComponent {...rest}>
|
|
||||||
<MDXRemote {...mdxSource} components={MDXComponents} />
|
|
||||||
</LayoutComponent>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,19 @@
|
|||||||
@apply hidden;
|
@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 {
|
html {
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: Sparrow Hawk
|
name: Sparrow Hawk
|
||||||
avatar: https://upload.wikimedia.org/wikipedia/commons/thumb/e/e8/Accnis_edit.jpg/220px-Accnis_edit.jpg
|
avatar: /static/images/sparrowhawk-avatar.jpg
|
||||||
occupation: Wizard of Earthsea
|
occupation: Wizard of Earthsea
|
||||||
company: Earthsea
|
company: Earthsea
|
||||||
twitter: https://twitter.com/sparrowhawk
|
twitter: https://twitter.com/sparrowhawk
|
||||||
|
@ -140,6 +140,7 @@ function fancyAlert(arg) {
|
|||||||
$.facebox({ div: '#foo' })
|
$.facebox({ div: '#foo' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
```
|
||||||
````
|
````
|
||||||
|
|
||||||
And here's how it looks - nicely colored with styled code titles!
|
And here's how it looks - nicely colored with styled code titles!
|
||||||
|
@ -50,14 +50,10 @@ _Note_: If you try to save the image, it is in webp format, if your browser supp
|
|||||||

|

|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Photo by{' '}
|
Photo by [YUCAR
|
||||||
<a href="https://unsplash.com/@yucar?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">
|
FotoGrafik](https://unsplash.com/@yucar?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
YUCAR FotoGrafik
|
on
|
||||||
</a>{' '}
|
[Unsplash](https://unsplash.com/s/photos/sea?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
on{' '}
|
|
||||||
<a href="https://unsplash.com/s/photos/sea?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">
|
|
||||||
Unsplash
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
# Benefits
|
# Benefits
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: 'New features in v1'
|
title: 'New features in v1'
|
||||||
date: '2021-06-02'
|
date: '2021-06-29'
|
||||||
tags: ['next-js', 'tailwind', 'guide']
|
tags: ['next-js', 'tailwind', 'guide']
|
||||||
draft: false
|
draft: false
|
||||||
summary: 'An overview of the new features released in v1 - code block copy, multiple authors, frontmatter layout and more'
|
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:
|
A post on the new features introduced in v1.0. New features:
|
||||||
|
|
||||||
- [Theme colors](#theme-colors)
|
- [Theme colors](#theme-colors)
|
||||||
|
- [Xdm MDX compiler](#xdm-mdx-compiler)
|
||||||
- [Layouts](#layouts)
|
- [Layouts](#layouts)
|
||||||
- [Multiple authors](#multiple-authors)
|
- [Multiple authors](#multiple-authors)
|
||||||
- [Copy button for code blocks](#copy-button-for-code-blocks)
|
- [Copy button for code blocks](#copy-button-for-code-blocks)
|
||||||
|
- [Line highlighting and line numbers](#line-highlighting-and-line-numbers)
|
||||||
|
|
||||||
## Theme colors
|
## Theme colors
|
||||||
|
|
||||||
You can easily modify the theme color by changing the primary attribute in the tailwind config file:
|
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: {
|
theme: {
|
||||||
colors: {
|
colors: {
|
||||||
primary: colors.teal,
|
primary: colors.teal,
|
||||||
@ -37,6 +39,37 @@ 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`.
|
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.
|
||||||
|
|
||||||
|
For example, the following jsx snippet can be used directly in an MDX file to render the page title component:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import PageTitle from './PageTitle.js'
|
||||||
|
|
||||||
|
;<PageTitle> Using JSX components in MDX </PageTitle>
|
||||||
|
```
|
||||||
|
|
||||||
|
import PageTitle from './PageTitle.js'
|
||||||
|
|
||||||
|
<PageTitle> Using JSX components in MDX </PageTitle>
|
||||||
|
|
||||||
|
The default configuration resolves all components relative to the `components` directory.
|
||||||
|
|
||||||
|
**Note**:
|
||||||
|
Components which require external image loaders would require additional esbuild configuration.
|
||||||
|
Components which are dependent on global application state on lifecycle like the Nextjs `Link` component would also not work with this setup as each mdx file is built indepedently.
|
||||||
|
For such cases, it is better to use component substitution.
|
||||||
|
|
||||||
## Layouts
|
## 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!
|
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 +143,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:
|
Here's how an author markdown file might looks like:
|
||||||
|
|
||||||
```:default.md
|
```md:default.md
|
||||||
---
|
---
|
||||||
name: Tails Azimuth
|
name: Tails Azimuth
|
||||||
avatar: /static/images/avatar.png
|
avatar: /static/images/avatar.png
|
||||||
@ -153,3 +186,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.
|
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 `<pre>` blocks.
|
The component is passed to `MDXComponents` and modifies all `<pre>` 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);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -59,42 +59,26 @@ When MDX v2 is ready, one could potentially interleave markdown in jsx directly!
|
|||||||
### Photo Credits
|
### Photo Credits
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
Maple photo by{' '}
|
Maple photo by [Guillaume
|
||||||
<a href="https://unsplash.com/@i_am_g?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">
|
Jaillet](https://unsplash.com/@i_am_g?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
Guillaume Jaillet
|
on
|
||||||
</a>{' '}
|
[Unsplash](https://unsplash.com/s/photos/canada?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
on{' '}
|
|
||||||
<a href="https://unsplash.com/s/photos/canada?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">
|
|
||||||
Unsplash
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Mountains photo by{' '}
|
Mountains photo by [John
|
||||||
<a href="https://unsplash.com/@john_artifexfilms?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">
|
Lee](https://unsplash.com/@john_artifexfilms?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
John Lee
|
on
|
||||||
</a>{' '}
|
[Unsplash](https://unsplash.com/s/photos/canada?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
on{' '}
|
|
||||||
<a href="https://unsplash.com/s/photos/canada?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">
|
|
||||||
Unsplash
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Lake photo by{' '}
|
Lake photo by [Tj
|
||||||
<a href="https://unsplash.com/@tjholowaychuk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">
|
Holowaychuk](https://unsplash.com/@tjholowaychuk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
Tj Holowaychuk
|
on
|
||||||
</a>{' '}
|
[Unsplash](https://unsplash.com/s/photos/canada?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
on{' '}
|
|
||||||
<a href="https://unsplash.com/s/photos/canada?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">
|
|
||||||
Unsplash
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Toronto photo by{' '}
|
Toronto photo by [Matthew
|
||||||
<a href="https://unsplash.com/@matthewhenry?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">
|
Henry](https://unsplash.com/@matthewhenry?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
Matthew Henry
|
on
|
||||||
</a>{' '}
|
[Unsplash](https://unsplash.com/s/photos/canada?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
on{' '}
|
|
||||||
<a href="https://unsplash.com/s/photos/canada?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">
|
|
||||||
Unsplash
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -55,7 +55,7 @@ export default function PostLayout({ frontMatter, authorDetails, next, prev, chi
|
|||||||
<li className="flex items-center space-x-2" key={author.name}>
|
<li className="flex items-center space-x-2" key={author.name}>
|
||||||
{author.avatar && (
|
{author.avatar && (
|
||||||
<Image
|
<Image
|
||||||
src={siteMetadata.image}
|
src={author.avatar}
|
||||||
width="38px"
|
width="38px"
|
||||||
height="38px"
|
height="38px"
|
||||||
alt="avatar"
|
alt="avatar"
|
||||||
|
@ -15,13 +15,14 @@ module.exports = (options) => (tree) => {
|
|||||||
const dimensions = sizeOf(`${process.cwd()}/public${imageNode.url}`)
|
const dimensions = sizeOf(`${process.cwd()}/public${imageNode.url}`)
|
||||||
|
|
||||||
// Convert original node to next/image
|
// Convert original node to next/image
|
||||||
imageNode.type = 'jsx'
|
;(imageNode.type = 'mdxJsxFlowElement'),
|
||||||
imageNode.value = `<Image
|
(imageNode.name = 'Image'),
|
||||||
alt={\`${imageNode.alt}\`}
|
(imageNode.attributes = [
|
||||||
src={\`${imageNode.url}\`}
|
{ type: 'mdxJsxAttribute', name: 'alt', value: imageNode.alt },
|
||||||
width={${dimensions.width}}
|
{ type: 'mdxJsxAttribute', name: 'src', value: imageNode.url },
|
||||||
height={${dimensions.height}}
|
{ type: 'mdxJsxAttribute', name: 'width', value: dimensions.width },
|
||||||
/>`
|
{ type: 'mdxJsxAttribute', name: 'height', value: dimensions.height },
|
||||||
|
])
|
||||||
|
|
||||||
// Change node type from p to div to avoid nesting error
|
// Change node type from p to div to avoid nesting error
|
||||||
node.type = 'div'
|
node.type = 'div'
|
||||||
|
64
lib/mdx.js
64
lib/mdx.js
@ -1,10 +1,10 @@
|
|||||||
import { MDXComponents } from '@/components/MDXComponents'
|
import { bundleMDX } from 'mdx-bundler'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import matter from 'gray-matter'
|
import matter from 'gray-matter'
|
||||||
import { serialize } from 'next-mdx-remote/serialize'
|
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import readingTime from 'reading-time'
|
import readingTime from 'reading-time'
|
||||||
import visit from 'unist-util-visit'
|
import visit from 'unist-util-visit'
|
||||||
|
import codeTitles from './remark-code-title'
|
||||||
import imgToJsx from './img-to-jsx'
|
import imgToJsx from './img-to-jsx'
|
||||||
import getAllFilesRecursively from './utils/files'
|
import getAllFilesRecursively from './utils/files'
|
||||||
|
|
||||||
@ -48,21 +48,45 @@ export async function getFileBySlug(type, slug) {
|
|||||||
? fs.readFileSync(mdxPath, 'utf8')
|
? fs.readFileSync(mdxPath, 'utf8')
|
||||||
: fs.readFileSync(mdPath, 'utf8')
|
: fs.readFileSync(mdPath, 'utf8')
|
||||||
|
|
||||||
const { data, content } = matter(source)
|
// https://github.com/kentcdodds/mdx-bundler#nextjs-esbuild-enoent
|
||||||
const mdxSource = await serialize(content, {
|
if (process.platform === 'win32') {
|
||||||
components: MDXComponents,
|
process.env.ESBUILD_BINARY_PATH = path.join(
|
||||||
mdxOptions: {
|
process.cwd(),
|
||||||
remarkPlugins: [
|
'node_modules',
|
||||||
|
'esbuild',
|
||||||
|
'esbuild.exe'
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
process.env.ESBUILD_BINARY_PATH = path.join(
|
||||||
|
process.cwd(),
|
||||||
|
'node_modules',
|
||||||
|
'esbuild',
|
||||||
|
'bin',
|
||||||
|
'esbuild'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { frontmatter, code } = await bundleMDX(source, {
|
||||||
|
// mdx imports can be automatically source from the components directory
|
||||||
|
cwd: path.join(process.cwd(), 'components'),
|
||||||
|
xdmOptions(options) {
|
||||||
|
// this is the recommended way to add custom remark/rehype plugins:
|
||||||
|
// The syntax might look weird, but it protects you in case we add/remove
|
||||||
|
// plugins in the future.
|
||||||
|
options.remarkPlugins = [
|
||||||
|
...(options.remarkPlugins ?? []),
|
||||||
require('remark-slug'),
|
require('remark-slug'),
|
||||||
require('remark-autolink-headings'),
|
require('remark-autolink-headings'),
|
||||||
require('remark-code-titles'),
|
require('remark-gfm'),
|
||||||
|
codeTitles,
|
||||||
|
[require('remark-footnotes'), { inlineNotes: true }],
|
||||||
require('remark-math'),
|
require('remark-math'),
|
||||||
imgToJsx,
|
imgToJsx,
|
||||||
],
|
]
|
||||||
inlineNotes: true,
|
options.rehypePlugins = [
|
||||||
rehypePlugins: [
|
...(options.rehypePlugins ?? []),
|
||||||
require('rehype-katex'),
|
require('rehype-katex'),
|
||||||
require('@mapbox/rehype-prism'),
|
[require('rehype-prism-plus'), { ignoreMissing: true }],
|
||||||
() => {
|
() => {
|
||||||
return (tree) => {
|
return (tree) => {
|
||||||
visit(tree, 'element', (node, index, parent) => {
|
visit(tree, 'element', (node, index, parent) => {
|
||||||
@ -73,17 +97,25 @@ export async function getFileBySlug(type, slug) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
],
|
]
|
||||||
|
return options
|
||||||
|
},
|
||||||
|
esbuildOptions: (options) => {
|
||||||
|
options.loader = {
|
||||||
|
...options.loader,
|
||||||
|
'.js': 'jsx',
|
||||||
|
}
|
||||||
|
return options
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
mdxSource,
|
mdxSource: code,
|
||||||
frontMatter: {
|
frontMatter: {
|
||||||
readingTime: readingTime(content),
|
readingTime: readingTime(code),
|
||||||
slug: slug || null,
|
slug: slug || null,
|
||||||
fileName: fs.existsSync(mdxPath) ? `${slug}.mdx` : `${slug}.md`,
|
fileName: fs.existsSync(mdxPath) ? `${slug}.mdx` : `${slug}.md`,
|
||||||
...data,
|
...frontmatter,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
32
lib/remark-code-title.js
Normal file
32
lib/remark-code-title.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import visit from 'unist-util-visit'
|
||||||
|
|
||||||
|
module.exports = function (options) {
|
||||||
|
return (tree) =>
|
||||||
|
visit(tree, 'code', (node, index) => {
|
||||||
|
const nodeLang = node.lang || ''
|
||||||
|
let language = ''
|
||||||
|
let title = ''
|
||||||
|
|
||||||
|
if (nodeLang.includes(':')) {
|
||||||
|
language = nodeLang.slice(0, nodeLang.search(':'))
|
||||||
|
title = nodeLang.slice(nodeLang.search(':') + 1, nodeLang.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!title) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const className = 'remark-code-title'
|
||||||
|
|
||||||
|
const titleNode = {
|
||||||
|
type: 'mdxJsxFlowElement',
|
||||||
|
name: 'div',
|
||||||
|
attributes: [{ type: 'mdxJsxAttribute', name: 'className', value: className }],
|
||||||
|
children: [{ type: 'text', value: title }],
|
||||||
|
data: { _xdmExplicitJsx: true },
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.children.splice(index, 0, titleNode)
|
||||||
|
node.lang = language
|
||||||
|
})
|
||||||
|
}
|
2196
package-lock.json
generated
2196
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@ -12,25 +12,25 @@
|
|||||||
"prepare": "husky install"
|
"prepare": "husky install"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mapbox/rehype-prism": "^0.6.0",
|
|
||||||
"@tailwindcss/forms": "^0.3.2",
|
"@tailwindcss/forms": "^0.3.2",
|
||||||
"@tailwindcss/typography": "^0.4.0",
|
"@tailwindcss/typography": "^0.4.0",
|
||||||
"autoprefixer": "^10.2.5",
|
"autoprefixer": "^10.2.5",
|
||||||
"gray-matter": "^4.0.2",
|
"gray-matter": "^4.0.2",
|
||||||
"image-size": "1.0.0",
|
"image-size": "1.0.0",
|
||||||
|
"mdx-bundler": "^4.1.0",
|
||||||
"next": "11.0.1",
|
"next": "11.0.1",
|
||||||
"next-mdx-remote": "^3.0.1",
|
|
||||||
"next-themes": "^0.0.14",
|
"next-themes": "^0.0.14",
|
||||||
"postcss": "^8.3.5",
|
"postcss": "^8.3.5",
|
||||||
"preact": "^10.5.13",
|
"preact": "^10.5.13",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2",
|
||||||
"reading-time": "1.3.0",
|
"reading-time": "1.3.0",
|
||||||
"rehype-katex": "^4.0.0",
|
"rehype-katex": "^5.0.0",
|
||||||
|
"rehype-prism-plus": "0.0.1",
|
||||||
"remark-autolink-headings": "6.0.1",
|
"remark-autolink-headings": "6.0.1",
|
||||||
"remark-code-titles": "0.1.2",
|
|
||||||
"remark-footnotes": "^3.0.0",
|
"remark-footnotes": "^3.0.0",
|
||||||
"remark-math": "^3.0.1",
|
"remark-gfm": "^1.0.0",
|
||||||
|
"remark-math": "^4.0.0",
|
||||||
"remark-slug": "6.0.0",
|
"remark-slug": "6.0.0",
|
||||||
"tailwindcss": "^2.2.2"
|
"tailwindcss": "^2.2.2"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Image from 'next/image'
|
|
||||||
import siteMetadata from '@/data/siteMetadata'
|
import siteMetadata from '@/data/siteMetadata'
|
||||||
import projectsData from '@/data/projectsData'
|
import projectsData from '@/data/projectsData'
|
||||||
|
import Image from '@/components/Image'
|
||||||
import Link from '@/components/Link'
|
import Link from '@/components/Link'
|
||||||
import Card from '@/components/Card'
|
import Card from '@/components/Card'
|
||||||
import { PageSeo } from '@/components/SEO'
|
import { PageSeo } from '@/components/SEO'
|
||||||
|
BIN
public/static/images/sparrowhawk-avatar.jpg
Normal file
BIN
public/static/images/sparrowhawk-avatar.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Loading…
x
Reference in New Issue
Block a user