Browse Source

fix: update next, custom mdx-loader

fix/enable-imgix
Thomas Osmonson 4 years ago
parent
commit
877faff581
  1. 46
      lib/mdx-loader.js
  2. 111
      next.config.js
  3. 2
      package.json
  4. 3
      src/common/utils/index.ts
  5. 4
      src/components/clarity-ref.tsx
  6. 3
      src/components/cli-reference.tsx
  7. 4
      src/components/faq.tsx
  8. 4
      src/components/glossary.tsx
  9. 44
      src/components/layouts/markdown-wrapper.tsx
  10. 67
      src/components/mdx/md-contents.tsx
  11. 5
      src/components/mdx/mdx-components.tsx
  12. 4
      src/components/mdx/styles.tsx
  13. 28
      yarn.lock

46
lib/md-loader.js → lib/mdx-loader.js

@ -1,8 +1,15 @@
const { getOptions } = require('loader-utils');
const mdx = require('@mdx-js/mdx');
const fm = require('gray-matter'); const fm = require('gray-matter');
const remark = require('remark'); const remark = require('remark');
const strip = require('strip-markdown'); const strip = require('strip-markdown');
const readingTime = require('reading-time'); const readingTime = require('reading-time');
const DEFAULT_RENDERER = `
import React from 'react'
import { mdx } from '@mdx-js/react'
`;
const getReadingTime = mdxContent => readingTime(mdxContent); const getReadingTime = mdxContent => readingTime(mdxContent);
const getHeadings = mdxContent => { const getHeadings = mdxContent => {
@ -27,24 +34,37 @@ const getHeadings = mdxContent => {
return headings; return headings;
}; };
// makes mdx in next.js suck less by injecting necessary exports so that const layoutPropsString = `const layoutProps = {`;
// the docs are still readable on github const newLayoutPropsString = frontmatter => `const layoutProps = {
// (Shamelessly stolen from Expo.io docs) frontmatter: ${frontmatter},\n`;
// @see https://github.com/expo/expo/blob/master/docs/common/md-loader.js
module.exports = async function (src) { const withFrontmatter = (code, frontmatter) =>
code.replace(layoutPropsString, newLayoutPropsString(frontmatter));
const loader = async function (src) {
const callback = this.async(); const callback = this.async();
const options = Object.assign({}, getOptions(this), {
filepath: this.resourcePath,
});
const { content, data } = fm(src); const { content, data } = fm(src);
const headings = getHeadings(content); const headings = getHeadings(content);
const duration = getReadingTime(content).text; const duration = getReadingTime(content).text;
const code = const frontmatter = JSON.stringify({ duration, ...data, headings });
`import { MDWrapper } from '@components/layouts/markdown-wrapper';
export const frontmatter = ${JSON.stringify({ duration, ...data, headings })};
const Layout = ({ children, ...props }) => (
<MDWrapper frontmatter={frontmatter} {...props}>{children}</MDWrapper>
)
export default Layout;
` + content; let result;
try {
result = await mdx(content, options);
} catch (err) {
return callback(err);
}
const { renderer = DEFAULT_RENDERER } = options;
const code = withFrontmatter(`${renderer}\n${result}`, frontmatter);
return callback(null, code); return callback(null, code);
}; };
module.exports = loader;

111
next.config.js

@ -8,26 +8,94 @@ const withFonts = require('next-fonts');
async function redirects() { async function redirects() {
return [ return [
{ source: '/browser/todo-list.html', destination: '', permanent: true }, {
{ source: '/develop/connect/get-started.html', destination: '', permanent: true }, source: '/browser/todo-list.html',
{ source: '/develop/connect/overview.html', destination: '', permanent: true }, destination: '/authentication/building-todo-app',
{ source: '/develop/profiles.html', destination: '', permanent: true }, permanent: true,
{ source: '/storage/overview.html', destination: '', permanent: true }, },
{ source: '/develop/storage.html', destination: '', permanent: true }, {
{ source: '/storage/authentication.html', destination: '', permanent: true }, source: '/develop/connect/get-started.html',
{ source: '/storage/write-to-read.html', destination: '', permanent: true }, destination: '/authentication/connect',
{ source: '/develop/radiks-intro.html', destination: '', permanent: true }, permanent: true,
{ source: '/develop/radiks-setup.html', destination: '', permanent: true }, },
{ source: '/develop/radiks-models.html', destination: '', permanent: true }, {
{ source: '/develop/radiks-collaborate.html', destination: '', permanent: true }, source: '/develop/connect/overview.html',
{ source: '/develop/radiks-server-extras.html', destination: '', permanent: true }, destination: '/authentication/connect',
{ source: '/core/smart/overview.html', destination: '', permanent: true }, permanent: true,
{ source: '/core/smart/tutorial.html', destination: '', permanent: true }, },
{ source: '/core/smart/tutorial-counter.html', destination: '', permanent: true }, { source: '/develop/profiles.html', destination: '/authentication/profiles', permanent: true },
{ source: '/core/smart/tutorial-test.html', destination: '', permanent: true }, { source: '/storage/overview.html', destination: '/data-storage/overview', permanent: true },
{ source: '/develop/connect/use-with-clarity.html', destination: '', permanent: true }, { source: '/develop/storage.html', destination: '/data-storage/overview', permanent: true },
{ source: '/core/smart/principals.html', destination: '', permanent: true }, {
{ source: '/core/smart/testnet-node.html', destination: '', permanent: true }, source: '/storage/authentication.html',
destination: '/data-storage/authentication',
permanent: true,
},
{
source: '/storage/write-to-read.html',
destination: '/data-storage/storage-write-read',
permanent: true,
},
{
source: '/develop/radiks-intro.html',
destination: '/data-indexing/overview',
permanent: true,
},
{
source: '/develop/radiks-setup.html',
destination: '/data-indexing/integrate',
permanent: true,
},
{
source: '/develop/radiks-models.html',
destination: '/data-indexing/models',
permanent: true,
},
{
source: '/develop/radiks-collaborate.html',
destination: '/data-indexing/collaborate',
permanent: true,
},
{
source: '/develop/radiks-server-extras.html',
destination: '/data-indexing/server-extras',
permanent: true,
},
{
source: '/core/smart/overview.html',
destination: '/smart-contracts/overview',
permanent: true,
},
{
source: '/core/smart/tutorial.html',
destination: '/smart-contracts/hello-world-tutorial',
permanent: true,
},
{
source: '/core/smart/tutorial-counter.html',
destination: '/smart-contracts/counter-tutorial',
permanent: true,
},
{
source: '/core/smart/tutorial-test.html',
destination: '/smart-contracts/testing-contracts',
permanent: true,
},
{
source: '/develop/connect/use-with-clarity.html',
destination: '/smart-contracts/signing-transactions',
permanent: true,
},
{
source: '/core/smart/principals.html',
destination: '/smart-contracts/principals',
permanent: true,
},
{
source: '/core/smart/testnet-node.html',
destination: '/smart-contracts/running-a-testnet-node',
permanent: true,
},
{ source: '/core/smart/cli-wallet-quickstart.html', destination: '', permanent: true }, { source: '/core/smart/cli-wallet-quickstart.html', destination: '', permanent: true },
{ source: '/core/naming/introduction.html', destination: '', permanent: true }, { source: '/core/naming/introduction.html', destination: '', permanent: true },
{ source: '/core/naming/architecture.html', destination: '', permanent: true }, { source: '/core/naming/architecture.html', destination: '', permanent: true },
@ -92,13 +160,12 @@ module.exports = withFonts(
use: [ use: [
options.defaultLoaders.babel, options.defaultLoaders.babel,
{ {
loader: '@mdx-js/loader', loader: './lib/mdx-loader',
options: { options: {
remarkPlugins, remarkPlugins,
rehypePlugins, rehypePlugins,
}, },
}, },
path.join(__dirname, './lib/md-loader'),
], ],
}); });

2
package.json

@ -34,7 +34,7 @@
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
"mdi-react": "7.3.0", "mdi-react": "7.3.0",
"micro-memoize": "^4.0.9", "micro-memoize": "^4.0.9",
"next": "^9.5.2-canary.5", "next": "^9.5.2-canary.6",
"next-fonts": "^1.4.0", "next-fonts": "^1.4.0",
"next-google-fonts": "^1.1.0", "next-google-fonts": "^1.1.0",
"next-mdx-remote": "^0.6.0", "next-mdx-remote": "^0.6.0",

3
src/common/utils/index.ts

@ -68,7 +68,8 @@ const getTitleFromHeading = (headings?: any[]) =>
: headings[0].content : headings[0].content
: undefined; : undefined;
export const getTitle = ({ title, headings }): string => title || getTitleFromHeading(headings); export const getTitle = ({ title, headings }: { title?: string; headings?: any[] }): string =>
title || getTitleFromHeading(headings);
export const transition = (timing = '0.2s', properties = 'all') => export const transition = (timing = '0.2s', properties = 'all') =>
`${properties} ${timing} cubic-bezier(0.23, 1, 0.32, 1)`; `${properties} ${timing} cubic-bezier(0.23, 1, 0.32, 1)`;

4
src/components/clarity-ref.tsx

@ -8,7 +8,7 @@ export const ClarityKeywordReference = ({ content, headings }) => {
return ( return (
<> <>
<TableOfContents mb={space('extra-loose')} label="Contents" headings={headings} /> <TableOfContents mb={space('extra-loose')} label="Contents" headings={headings} />
{hydrate(content, MDXComponents)} {hydrate(content, { ...MDXComponents, wrapper: undefined })}
</> </>
); );
}; };
@ -20,6 +20,6 @@ export const ClarityFunctionReference = ({ content, headings }) => (
label="Contents" label="Contents"
headings={headings} headings={headings}
/> />
{hydrate(content, MDXComponents)} {hydrate(content, { ...MDXComponents, wrapper: undefined })}
</> </>
); );

3
src/components/cli-reference.tsx

@ -3,7 +3,7 @@ import { cliReferenceData } from '@common/../_data/cliRef';
import { MDXComponents } from '@components/mdx/mdx-components'; import { MDXComponents } from '@components/mdx/mdx-components';
import { Grid, Box, color } from '@blockstack/ui'; import { Grid, Box, color } from '@blockstack/ui';
import { border } from '@common/utils'; import { border } from '@common/utils';
import { hydrate } from '@common/data/hydrate-mdx'; import hydrate from 'next-mdx-remote/hydrate';
const styles = { const styles = {
maxWidth: '100%', maxWidth: '100%',
@ -23,6 +23,7 @@ const ReferenceEntry = ({ entry, usage }) => (
{hydrate(usage, { {hydrate(usage, {
...MDXComponents, ...MDXComponents,
wrapper: undefined,
p: (props: any) => ( p: (props: any) => (
<MDXComponents.p <MDXComponents.p
{...props} {...props}

4
src/components/faq.tsx

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { MDXComponents } from '@components/mdx'; import { MDXComponents } from '@components/mdx';
import { Box, Flex, ChevronIcon, space, color } from '@blockstack/ui'; import { Box, Flex, ChevronIcon, space, color } from '@blockstack/ui';
import { hydrate } from '@common/data/hydrate-mdx'; import hydrate from 'next-mdx-remote/hydrate';
import { Accordion, AccordionItem, AccordionButton, AccordionPanel } from '@reach/accordion'; import { Accordion, AccordionItem, AccordionButton, AccordionPanel } from '@reach/accordion';
import { border } from '@common/utils'; import { border } from '@common/utils';
import { slugify } from '@common/utils'; import { slugify } from '@common/utils';
@ -51,7 +51,7 @@ const FAQItem = React.memo(({ faq, ...rest }: any) => {
</Box> </Box>
</Flex> </Flex>
<Box px={space('extra-loose')} pb={space('extra-loose')} as={AccordionPanel}> <Box px={space('extra-loose')} pb={space('extra-loose')} as={AccordionPanel}>
{hydrate(faq.answer, MDXComponents)} {hydrate(faq.answer, { ...MDXComponents, wrapper: undefined })}
</Box> </Box>
</Box> </Box>
); );

4
src/components/glossary.tsx

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { Box, space } from '@blockstack/ui'; import { Box, space } from '@blockstack/ui';
import { hydrate } from '@common/data/hydrate-mdx'; import hydrate from 'next-mdx-remote/hydrate';
import { MDXComponents } from '@components/mdx/mdx-components'; import { MDXComponents } from '@components/mdx/mdx-components';
import { slugify } from '@common/utils'; import { slugify } from '@common/utils';
import { css } from '@styled-system/css'; import { css } from '@styled-system/css';
@ -37,7 +37,7 @@ export const Glossary = ({ data }) => {
}, },
})} })}
> >
{hydrate(entry.definition, MDXComponents)} {hydrate(entry.definition, { ...MDXComponents, wrapper: undefined })}
</Box> </Box>
</> </>
))} ))}

44
src/components/layouts/markdown-wrapper.tsx

@ -13,7 +13,7 @@ const Search = dynamic(() => import('@components/search'));
const PageTop = props => { const PageTop = props => {
const router = useRouter(); const router = useRouter();
const isHome = router.pathname === '/'; const isHome = router?.pathname === '/';
return ( return (
<Box <Box
mb={['extra-loose', 'extra-loose', '64px']} mb={['extra-loose', 'extra-loose', '64px']}
@ -47,23 +47,31 @@ const PageTop = props => {
); );
}; };
export const MDWrapper = ({ frontmatter, dynamicHeadings = [], ...props }) => { const defaultFrontmatter = {
const { headings, description } = frontmatter; headings: [],
description:
return ( 'Blockstack is an open-source and developer-friendly network for building decentralized apps and smart contracts.',
<>
<Head>
<title>{getTitle(frontmatter)} | Blockstack</title>
<meta name="description" content={description} />
</Head>
<MDContents
pageTop={() => <PageTop {...frontmatter} />}
headings={[...headings, ...dynamicHeadings]}
>
{props.children}
</MDContents>
</>
);
}; };
export const MDWrapper: React.FC<any> = React.memo(
({ frontmatter = defaultFrontmatter, dynamicHeadings = [], ...props }) => {
const { headings, description } = frontmatter;
return (
<>
<Head>
<title>{getTitle(frontmatter)} | Blockstack</title>
<meta name="description" content={description} />
</Head>
<MDContents
pageTop={() => <PageTop {...frontmatter} />}
headings={[...headings, ...dynamicHeadings]}
>
{props.children}
</MDContents>
</>
);
}
);
export default MDWrapper; export default MDWrapper;

67
src/components/mdx/md-contents.tsx

@ -13,44 +13,35 @@ import dynamic from 'next/dynamic';
const Search = dynamic(() => import('@components/search')); const Search = dynamic(() => import('@components/search'));
export const MDContents: React.FC<any> = React.memo( export const MDContents: React.FC<any> = ({ pageTop: PageTop = null, headings, children }) => {
({ pageTop: PageTop = null, headings, children }) => { const router = useRouter();
const router = useRouter(); const isHome = router?.pathname === '/';
const isHome = router.pathname === '/';
const TOCShowing = !isHome && headings?.length > 1; const TOCShowing = !isHome && headings && headings?.length > 1;
return ( return (
<> <>
<ContentWrapper <ContentWrapper
width={['100%', '100%', '100%', `calc(100% - ${!TOCShowing ? 0 : TOC_WIDTH}px)`]} width={['100%', '100%', '100%', `calc(100% - ${!TOCShowing ? 0 : TOC_WIDTH}px)`]}
mx="unset" mx="unset"
pt="unset" pt="unset"
css={css(styleOverwrites as any)} css={css(styleOverwrites as any)}
pr={TOCShowing && ['0', '0', '0', 'extra-loose']} pr={TOCShowing && ['0', '0', '0', 'extra-loose']}
>
{PageTop && <PageTop />}
{children}
</ContentWrapper>
{!isHome ? (
<Box
maxWidth={['100%', `${TOC_WIDTH}px`, `${TOC_WIDTH}px`]}
width="100%"
display={['none', 'none', 'none', 'block']}
> >
{PageTop && <PageTop />} <Box position="sticky" top={0} pt="64px">
{children} <Search mb={space('extra-loose')} />
</ContentWrapper> {TOCShowing ? null : null}
{!isHome ? (
<Box
maxWidth={['100%', `${TOC_WIDTH}px`, `${TOC_WIDTH}px`]}
width="100%"
display={['none', 'none', 'none', 'block']}
>
<Box position="sticky" top={0} pt="64px">
<Search mb={space('extra-loose')} />
{TOCShowing ? (
<TableOfContents
pl={space('base')}
borderLeft={border()}
headings={headings}
limit={2}
/>
) : null}
</Box>
</Box> </Box>
) : null} </Box>
</> ) : null}
); </>
} );
); };

5
src/components/mdx/mdx-components.tsx

@ -1,4 +1,4 @@
import React, { Children } from 'react'; import React from 'react';
import { import {
Pre, Pre,
THead, THead,
@ -6,7 +6,6 @@ import {
TData, TData,
Table, Table,
InlineCode, InlineCode,
H1,
H2, H2,
H3, H3,
H4, H4,
@ -25,6 +24,7 @@ import {
import { Img } from '@components/mdx/image'; import { Img } from '@components/mdx/image';
import { Code } from '@components/mdx/components'; import { Code } from '@components/mdx/components';
import { PageReference } from '@components/custom-blocks/page-reference'; import { PageReference } from '@components/custom-blocks/page-reference';
import { MDWrapper } from '@components/layouts/markdown-wrapper';
export const MDXComponents = { export const MDXComponents = {
h1: () => null, h1: () => null,
@ -51,4 +51,5 @@ export const MDXComponents = {
sup: Sup, sup: Sup,
section: Section, section: Section,
pagereference: PageReference, pagereference: PageReference,
wrapper: MDWrapper,
}; };

4
src/components/mdx/styles.tsx

@ -9,6 +9,10 @@ export const MdxOverrides = createGlobalStyle`
* { * {
font-feature-settings: 'ss01' on; font-feature-settings: 'ss01' on;
} }
section{
content-visibility: auto;
contain-intrinsic-size: 1000px;
}
html, body { html, body {
font-family: 'Soehne', Inter, sans-serif; font-family: 'Soehne', Inter, sans-serif;
} }

28
yarn.lock

@ -1526,10 +1526,10 @@
resolved "https://registry.yarnpkg.com/@next/mdx/-/mdx-9.5.1.tgz#c7e2fd457810b34e8ce598f57075b799ca48751b" resolved "https://registry.yarnpkg.com/@next/mdx/-/mdx-9.5.1.tgz#c7e2fd457810b34e8ce598f57075b799ca48751b"
integrity sha512-jmNKqEMWkCPQWWeoq6CiOShngGv99Cs+rQSLlU7BZMVCZzbcTVEkAsUqR4WfLA97K2ihjtNidY5jwbKFu4h83Q== integrity sha512-jmNKqEMWkCPQWWeoq6CiOShngGv99Cs+rQSLlU7BZMVCZzbcTVEkAsUqR4WfLA97K2ihjtNidY5jwbKFu4h83Q==
"@next/react-dev-overlay@9.5.2-canary.5": "@next/react-dev-overlay@9.5.2-canary.6":
version "9.5.2-canary.5" version "9.5.2-canary.6"
resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-9.5.2-canary.5.tgz#b04f84a4df8d4a49239b8264b5156487c2a6f393" resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-9.5.2-canary.6.tgz#a1c057fc3d64abe6f2aa4caa50639cb1e3d83e5e"
integrity sha512-YaO0gIHC6/VrrbN/2FeN96pCcrsJAVGmxa1TUHEq2djzzv2NCh0MXnGzqWfbeQGYshjLzHNksDpfZgdHujncqg== integrity sha512-j7OL0bWMSTJO4YlMgiyRJ3MPphfeVtlQzZSeZJAGDuTDt3TSdMNo05HElgsYgZR9g2NVGIJkOqxZaz5+P/fggg==
dependencies: dependencies:
"@babel/code-frame" "7.8.3" "@babel/code-frame" "7.8.3"
ally.js "1.4.1" ally.js "1.4.1"
@ -1542,10 +1542,10 @@
stacktrace-parser "0.1.10" stacktrace-parser "0.1.10"
strip-ansi "6.0.0" strip-ansi "6.0.0"
"@next/react-refresh-utils@9.5.2-canary.5": "@next/react-refresh-utils@9.5.2-canary.6":
version "9.5.2-canary.5" version "9.5.2-canary.6"
resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-9.5.2-canary.5.tgz#314c04d281018157eda010c351548cbf3cc8ca48" resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-9.5.2-canary.6.tgz#0e7ef8f4759af55add1115da1b8a3ed085f61df7"
integrity sha512-mYT+8yMHlLQ5jSwibwKOCnsMY2qnlZ/caNI5qwTRH+ugKdyTNyFONm9d54KT9umdXei3azlkWJc0CI/Ceuo8mw== integrity sha512-5Y4u7tHb8VIv0tAWqBj020lucp3VvfUYn8aI5hbu3bgvHvuWbffJ8MOlIQeLIMD9qzjeNz+far+Q6SDvFHH1aQ==
"@popperjs/core@^2.4.0": "@popperjs/core@^2.4.0":
version "2.4.4" version "2.4.4"
@ -6324,10 +6324,10 @@ next-transpile-modules@^4.0.2:
micromatch "^4.0.2" micromatch "^4.0.2"
slash "^3.0.0" slash "^3.0.0"
next@^9.5.2-canary.5: next@^9.5.2-canary.6:
version "9.5.2-canary.5" version "9.5.2-canary.6"
resolved "https://registry.yarnpkg.com/next/-/next-9.5.2-canary.5.tgz#3743800daa0271fd97d4f037ba9ef74688f3b849" resolved "https://registry.yarnpkg.com/next/-/next-9.5.2-canary.6.tgz#0ea1194028cd49427eb761d19e654f01a94cf138"
integrity sha512-a5XTn8T5D88seubihcclRnf0ZKD0lz2cvYVH+aSi9pbUSyzKrG0yHNi1dauXXtba+CUFxvLn8BTWjmFXPy0W+g== integrity sha512-fCCQrQs42x6N//Nb88ZT2gsI7awIdtqu4nVHw/lLhahQGyHefb/8yDol0b2Zpud9siyj1FwfIMpVxRSOnZCsjg==
dependencies: dependencies:
"@ampproject/toolbox-optimizer" "2.5.14" "@ampproject/toolbox-optimizer" "2.5.14"
"@babel/code-frame" "7.8.3" "@babel/code-frame" "7.8.3"
@ -6348,8 +6348,8 @@ next@^9.5.2-canary.5:
"@babel/preset-typescript" "7.9.0" "@babel/preset-typescript" "7.9.0"
"@babel/runtime" "7.9.6" "@babel/runtime" "7.9.6"
"@babel/types" "7.9.6" "@babel/types" "7.9.6"
"@next/react-dev-overlay" "9.5.2-canary.5" "@next/react-dev-overlay" "9.5.2-canary.6"
"@next/react-refresh-utils" "9.5.2-canary.5" "@next/react-refresh-utils" "9.5.2-canary.6"
ast-types "0.13.2" ast-types "0.13.2"
babel-plugin-syntax-jsx "6.18.0" babel-plugin-syntax-jsx "6.18.0"
babel-plugin-transform-define "2.0.0" babel-plugin-transform-define "2.0.0"

Loading…
Cancel
Save