This commit is contained in:
Morten Olsen
2022-03-30 16:34:56 +02:00
committed by Morten Olsen
parent b654ba7e74
commit e6e938bd42
44 changed files with 386 additions and 263 deletions

View File

@@ -10,9 +10,9 @@ const withLatex = (nextConfig = {}) => {
outputPath = "../../";
}
config.module.rules.push({
test: /\.png.yml$/,
test: /\.gen.yml$/,
use: [{
loader: 'file-loader',
loader: require.resolve('./webpack.js'),
options: {
publicPath: `${nextConfig.assetPrefix || nextConfig.basePath || ''}/_next/static/images/`,
@@ -27,8 +27,6 @@ const withLatex = (nextConfig = {}) => {
},
esModule: nextConfig.esModule || false,
},
}, {
loader: require.resolve('./webpack.js'),
}],
});
if (typeof nextConfig.webpack === "function") {

View File

@@ -0,0 +1,31 @@
require('reflect-metadata');
require('@babel/register')({
extensions: [".es6", ".es", ".jsx", ".js", ".mjs", ".ts"],
});
const loaderUtils = require('loader-utils');
const path = require('path');
const yaml = require('yaml');
const { generate } = require('../../../src/generators');
module.exports = function (source) {
var callback = this.async();
const location = this.resourcePath;
const definition = yaml.parse(source);
const options = this.getOptions();
generate(definition, location)
.then((output) => {
const files = Object.entries(output).reduce((output, [key, value]) => {
const { name, content } = value;
const targetName = loaderUtils.interpolateName(this, `[contenthash]/${name}`, {content: content});
const location = path.join(options.outputPath, targetName);
const publicPath = path.join(options.publicPath, targetName);
this.emitFile(location, content);
return {
...output,
[key]: publicPath,
}
}, {});
callback(null, `module.exports = ${JSON.stringify(files)}`);
})
.catch(callback);
}

View File

@@ -1,16 +0,0 @@
require('reflect-metadata');
require('@babel/register')({
extensions: [".es6", ".es", ".jsx", ".js", ".mjs", ".ts"],
});
const { generateImage } = require('../../../src/images');
module.exports = function (source) {
var callback = this.async();
const location = this.resourcePath;
generateImage(source, location)
.then((canvas) => {
const buffer = canvas.toBuffer('image/png', {})
callback(null, buffer);
})
.catch(callback);
}

View File

@@ -1,34 +0,0 @@
const withLatex = (nextConfig = {}) => {
return Object.assign({}, nextConfig, {
webpack(config, options) {
const {isServer, dev} = options;
let outputPath = '';
if (isServer && dev) {
outputPath = "../";
} else if (isServer) {
outputPath = "../../";
}
config.module.rules.push({
test: /\.tex.yml$/,
use: [{
loader: 'file-loader',
options: {
publicPath: `${nextConfig.assetPrefix || nextConfig.basePath || ''}/_next/static/images/`,
outputPath: `${outputPath}static/images/`,
name: "[name]-[hash].pdf",
esModule: nextConfig.esModule || false,
},
}, {
loader: require.resolve('./webpack.js'),
}],
});
if (typeof nextConfig.webpack === "function") {
return nextConfig.webpack(config, options);
}
return config;
},
});
}
module.exports = withLatex;

View File

@@ -1,31 +0,0 @@
require('reflect-metadata');
require('@babel/register')({
extensions: [".es6", ".es", ".jsx", ".js", ".mjs", ".ts"],
});
const latex = require("node-latex")
var Readable = require('stream').Readable
const { generateLatex } = require('../../../src/latex');
module.exports = function (source) {
var callback = this.async();
const location = this.resourcePath;
generateLatex(source, location)
.then((result) => {
const chunks = [];
const input = new Readable();
input.push(result);
input.push(null);
const latexStream = latex(input);
latexStream.on('data', (chunk) => {
chunks.push(Buffer.from(chunk));
})
latexStream.on('finish', () => {
const result = Buffer.concat(chunks);
callback(null, result);
})
latexStream.on('error', (err) => {
callback(err);
})
})
.catch(callback);
}

View File

@@ -0,0 +1,4 @@
data:
type: article
structure: ./index.yml
generator: latex

View File

@@ -1,3 +0,0 @@
data:
structure: ./index.yml
generator: article

View File

@@ -1,6 +1,6 @@
title: How to hire engineers, by an engineer
cover: cover.png
published: 2022-03-16
shareImage: ./share.png.yml
shareImage: ./share.gen.yml
parts:
- main.md

View File

@@ -0,0 +1,5 @@
generator: image
data:
type: share
width: 450
height: 300

View File

@@ -1,3 +0,0 @@
generator: share
width: 450
height: 300

View File

@@ -0,0 +1,4 @@
data:
structure: ./index.yml
type: article
generator: latex

View File

@@ -1,3 +0,0 @@
data:
structure: ./index.yml
generator: article

View File

@@ -0,0 +1,4 @@
data:
type: article
structure: ./index.yml
generator: latex

View File

@@ -1,3 +0,0 @@
data:
structure: ./index.yml
generator: article

View File

@@ -1,6 +1,5 @@
title: My home runs Redux
cover: cover.png
published: 2022-03-15
shareImage: ./share.png.yml
parts:
- main.md

View File

@@ -1,3 +0,0 @@
generator: share
width: 450
height: 300

View File

@@ -0,0 +1,3 @@
generator: latex
data:
type: resume

View File

@@ -1 +0,0 @@
generator: resume

View File

@@ -0,0 +1,7 @@
generator: image
data:
type: resize
width: 780
height: 780
src: ./me.jpg
output: image/jpeg

View File

@@ -1,6 +1,7 @@
name: Morten Olsen
tagline: “...One part genius, one part crazy”
avatar: me.jpg
avatar: ./image.gen.yml
resumeImage: ./me.jpg
email: hello@buy-me.coffee
github: morten-olsen
location: Copenhagen, DK

View File

@@ -1,8 +1,7 @@
const withPlugins = require("next-compose-plugins");
const withImages = require("./config/plugins/withImages.js");
const withLatex = require('./config/plugins/withLatex');
const withImageGenerator = require('./config/plugins/withImageGenerator');
const withGenerator = require('./config/plugins/withGenerator');
const withBundleAnalyzer = require("@next/bundle-analyzer")({
enabled: process.env.ANALYZE === "true",
});
@@ -11,12 +10,14 @@ const nextConfig = {
poweredByHeader: false,
images: {
disableStaticImages: true
}
},
experimental: {
concurrentFeatures: true,
},
};
module.exports = withPlugins([
withLatex,
withImageGenerator,
withGenerator,
[withImages,{
esModule: true, // using ES modules is beneficial in the case of module concatenation and tree shaking.
inlineImageLimit: 0, // disable image inlining to data:base64

View File

@@ -12,10 +12,10 @@
"@react-three/drei": "^8.18.6",
"@react-three/fiber": "^7.0.26",
"date-fns": "^2.28.0",
"next": "^12.1.0",
"next": "^12.1.2",
"node-latex": "^3.1.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react": "^17",
"react-dom": "^17",
"react-markdown": "^8.0.1",
"reflect-metadata": "^0.1.13",
"rehype-img-size": "^1.0.1",

View File

@@ -36,19 +36,12 @@ const Cloud = ({ texture }) => {
const ref = useRef<any>();
const width = window.innerWidth / 2;
const height = window.innerHeight / 2;
const [ready, setReady] = useState(false);
useFrame(() => {
if (!ref.current || !ready) return;
if (!ref.current) return;
ref.current.rotation.z -= 0.003;
});
useEffect(() => {
setTimeout(() => {
setReady(true);
}, 500)
}, []);
return (
<mesh
ref={ref}
@@ -138,3 +131,4 @@ const HeroBackground = () => {
}
export { HeroBackground };
export default HeroBackground;

View File

@@ -1,7 +1,6 @@
import React from 'react';
import React, { Suspense, useEffect, useState } from 'react';
import styled from 'styled-components';
import { Profile } from '../../data/repos/profile';
import { HeroBackground } from './background';
import { SlideIn } from '../animations/slide-in';
type Props = {
@@ -91,7 +90,18 @@ const SocialLogo = styled.div<{ src: string }>`
background-size: cover;
`
const Hero: React.FC<Props> = ({ profile }) => (
const Hero: React.FC<Props> = ({ profile }) => {
const [background, setBackground] = useState<any>();
useEffect(
() => {
import('./background').then(({ default: HeroBackground }) => {
console.log('goo', typeof HeroBackground);
setBackground(<HeroBackground />);
})
},
[],
)
return (
<Wrapper>
<Avatar src={profile.avatar}>
<AvatarSpacer />
@@ -115,7 +125,9 @@ const Hero: React.FC<Props> = ({ profile }) => (
</SlideIn>
))}
</Social>
{background}
</Wrapper>
);
);
}
export { Hero };

View File

@@ -4,7 +4,7 @@ import { AssetResolver } from './';
const assetModules = (require as any).context(
'../../../content',
true,
/\.(png|jpe?g|svg|gif|tex\.yml|png\.yml)$/,
/\.(png|jpe?g|svg|gif|gen\.yml)$/,
)
const assets = assetModules.keys().reduce((output, key: string) => ({
...output,

View File

@@ -2,7 +2,7 @@ import { Service } from "typedi";
@Service()
abstract class AssetResolver {
public abstract getPath(...loc: string[]): string;
public abstract getPath(...loc: string[]): any;
}
export { AssetResolver };

View File

@@ -72,8 +72,8 @@ export class ArticleDB {
stats,
pdfs: {
a4: this.#assets.getPath(
path.resolve('/', 'articles', id, 'a4.tex.yml'),
) || null,
path.resolve('/', 'articles', id, 'a4.gen.yml'),
)?.url || null,
}
};

View File

@@ -18,7 +18,8 @@ export type Profile = {
value: string;
link: string;
logo: string;
}[]
}[];
resumeImage?: string;
platforms: {
name: string;
level: number;
@@ -50,9 +51,16 @@ export class ProfileDB {
const image = this.#assets.getPath(
'profile',
structure.avatar,
)
)?.url
structure.avatar = image || null;
}
if (structure.resumeImage) {
const image = this.#assets.getPath(
'profile',
structure.resumeImage,
)
structure.resumeImage = image || null;
}
structure.social = structure.social.map((social) => {
const image = this.#assets.getPath('profile', social.logo);
return {
@@ -62,8 +70,8 @@ export class ProfileDB {
})
structure.resume = this.#assets.getPath(
'profile',
'a4.tex.yml',
);
'a4.gen.yml',
)?.url || null;
return structure;
}

View File

@@ -0,0 +1,21 @@
import { createCanvas } from 'canvas';
import { Generator } from '../types';
import { generators } from './types';
const mimeToExt = {
'image/jpeg': 'jpg',
}
export const generateImage: Generator = async (data, location) => {
const { type, output, ...rest } = data;
const canvas = createCanvas(data.width, data.height)
const generator = generators[type];
await generator(rest, location, canvas);
const ext = mimeToExt[output] || 'png';
return {
url: {
name: `img.${ext}`,
content: canvas.toBuffer(output),
}
};
}

View File

@@ -1,8 +1,10 @@
import { ImageGenerator } from "./Generator";
import { ImageGenerator } from "./types";
import { shareGenerator } from "./share";
import { resizeGenerator } from "./resize";
const generators: {[name: string]: ImageGenerator} = {
share: shareGenerator,
resize: resizeGenerator,
};
export { generators };

View File

@@ -0,0 +1,86 @@
import { loadImage, CanvasRenderingContext2D, Image, createCanvas } from 'canvas';
import path from 'path';
import Container from "typedi";
import { AssetResolver } from "../../../data/assets";
import { ArticleDB } from "../../../data/repos/articles";
import { ImageGenerator } from "./types";
import { ProfileDB } from '../../../data/repos/profile';
const assets = {
getPath: (...source: string[]) => {
return path.join(process.cwd(), 'content', ...source);
},
}
function drawImageProp(
ctx: CanvasRenderingContext2D,
img: Image,
x?: number,
y?: number,
w?: number,
h?: number,
offsetX?: number,
offsetY?: number,
) {
if (arguments.length === 2) {
x = y = 0;
w = ctx.canvas.width;
h = ctx.canvas.height;
}
// default offset is center
offsetX = typeof offsetX === "number" ? offsetX : 0.5;
offsetY = typeof offsetY === "number" ? offsetY : 0.5;
// keep bounds [0.0, 1.0]
if (offsetX < 0) offsetX = 0;
if (offsetY < 0) offsetY = 0;
if (offsetX > 1) offsetX = 1;
if (offsetY > 1) offsetY = 1;
var iw = img.width,
ih = img.height,
r = Math.min(w / iw, h / ih),
nw = iw * r, // new prop. width
nh = ih * r, // new prop. height
cx, cy, cw, ch, ar = 1;
// decide which gap to fill
if (nw < w) ar = w / nw;
if (Math.abs(ar - 1) < 1e-14 && nh < h) ar = h / nh; // updated
nw *= ar;
nh *= ar;
// calc source rectangle
cw = iw / (nw / w);
ch = ih / (nh / h);
cx = (iw - cw) * offsetX;
cy = (ih - ch) * offsetY;
// make sure source rectangle is valid
if (cx < 0) cx = 0;
if (cy < 0) cy = 0;
if (cw > iw) cw = iw;
if (ch > ih) ch = ih;
// fill image in dest. rectangle
ctx.drawImage(img, cx, cy, cw, ch, x, y, w, h);
}
const resizeGenerator: ImageGenerator = async (data, location, canvas) => {
const dir = path.dirname(location);
const src = path.join(dir, data.src);
Container.set(AssetResolver, assets)
const ctx = canvas.getContext('2d');
ctx.antialias = 'subpixel';
const cover = await loadImage(src);
drawImageProp(
ctx,
cover,
)
};
export { resizeGenerator };

View File

@@ -1,11 +1,10 @@
import { loadImage, CanvasRenderingContext2D, Image, createCanvas } from 'canvas';
import path from 'path';
import Container from "typedi";
import { AssetResolver } from "../../data/assets";
import { ArticleDB } from "../../data/repos/articles";
import { ImageGenerator } from "./Generator";
import drawMultiLine from 'canvas-multiline-text';
import { ProfileDB } from '../../data/repos/profile';
import { AssetResolver } from "../../../data/assets";
import { ArticleDB } from "../../../data/repos/articles";
import { ImageGenerator } from "./types";
import { ProfileDB } from '../../../data/repos/profile';
const assets = {
getPath: (...source: string[]) => {

16
src/generators/index.ts Normal file
View File

@@ -0,0 +1,16 @@
import { Generator } from "./types";
import { generateImage } from "./images";
import { generateLatex } from "./latex";
const generators: {[name: string]: Generator} = {
image: generateImage,
latex: generateLatex,
}
const generate = async (definition: any, location: string) => {
const { data, generator } = definition;
const generatorFn = generators[generator];
const result = await generatorFn(data, location);
return result;
};
export { generate };

View File

@@ -1,7 +1,7 @@
import type { Article } from "../../../data/repos/articles";
import type { Article } from "../../../../data/repos/articles";
import fs from 'fs-extra';
import { LatexGenerator } from "../Generator";
import { generate } from '../../../data/helpers/markdown';
import { generate } from '../../../../data/helpers/markdown';
import path from 'path';
import yaml from 'yaml';
import { fromMarkdown } from "../../helpers/convert";

View File

@@ -1,9 +1,9 @@
import path from 'path';
import { LatexGenerator } from "../Generator";
import Container from 'typedi';
import { AssetResolver } from '../../../data/assets';
import { ProfileDB } from '../../../data/repos/profile';
import { ExperienceDB } from '../../../data/repos/experiences';
import { AssetResolver } from '../../../../data/assets';
import { ProfileDB } from '../../../../data/repos/profile';
import { ExperienceDB } from '../../../../data/repos/experiences';
import { fromMarkdown } from '../../helpers/convert';
const assets = {
@@ -20,9 +20,8 @@ const resume: LatexGenerator<Data> = async (data, location) => {
const experienceDB = Container.get(ExperienceDB);
const profile = await profileDB.get();
const avatar = profile.avatar;
const avatar = profile.resumeImage;
const experiences = await experienceDB.list();
console.log('a', avatar);
return `
\\documentclass[10pt, a4paper]{article}

View File

@@ -63,7 +63,6 @@ const renderer = (outerDepth: number) => ({
return `\\texttt{${sanitize(code)}}`
},
image: (link: string) => {
console.log('link', link);
if (!existsSync(link)) {
return 'Online image not supported';
}

View File

@@ -0,0 +1,37 @@
import latex from 'node-latex';
import { Readable } from 'stream';
import { Generator } from '../types';
import { generators } from "./generators";
const latexToPdf = (doc: string) => new Promise<Buffer>((resolve, reject) => {
const chunks = [];
const input = new Readable();
input.push(doc);
input.push(null);
const latexStream = latex(input);
latexStream.on('data', (chunk) => {
chunks.push(Buffer.from(chunk));
})
latexStream.on('finish', () => {
const result = Buffer.concat(chunks);
resolve(result);
})
latexStream.on('error', (err) => {
reject(err);
})
});
const generateLatex: Generator = async (data: any, location: string) => {
const { type, ...rest } = data;
const generator = generators[type];
const doc = await generator(rest, location);
const content = await latexToPdf(doc);
return {
url: {
name: 'doc.pdf',
content,
}
};
}
export { generateLatex };

7
src/generators/types.ts Normal file
View File

@@ -0,0 +1,7 @@
export type Generator<TData = any> = (data: TData, location: string) => Promise<{
[key: string]: {
name: string;
content: string | Buffer;
}
}>;

View File

@@ -1,11 +0,0 @@
import { createCanvas } from 'canvas';
import yaml from 'yaml';
import { generators } from './generator';
export const generateImage = async (source: string, location: string) => {
const definition = yaml.parse(source);
const canvas = createCanvas(definition.width * 2, definition.height * 2)
const generator = generators[definition.generator];
await generator(definition.data, location, canvas);
return canvas;
}

View File

@@ -1,12 +0,0 @@
import { generators } from "./generators";
import yaml from 'yaml';
import path from 'path';
const generateLatex = async (source: string, location: string) => {
const definition = yaml.parse(source);
const generator = generators[definition.generator];
const latex = await generator(definition.data, location);
return latex;
}
export { generateLatex };

148
yarn.lock
View File

@@ -458,65 +458,70 @@
dependencies:
webpack-bundle-analyzer "4.3.0"
"@next/env@12.1.0":
version "12.1.0"
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.0.tgz#73713399399b34aa5a01771fb73272b55b22c314"
integrity sha512-nrIgY6t17FQ9xxwH3jj0a6EOiQ/WDHUos35Hghtr+SWN/ntHIQ7UpuvSi0vaLzZVHQWaDupKI+liO5vANcDeTQ==
"@next/env@12.1.2":
version "12.1.2"
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.2.tgz#4b0f5fd448ac60b821d2486d2987948e3a099f03"
integrity sha512-A/P4ysmFScBFyu1ZV0Mr1Y89snyQhqGwsCrkEpK+itMF+y+pMqBoPVIyakUf4LXqGWJGiGFuIerihvSG70Ad8Q==
"@next/swc-android-arm64@12.1.0":
version "12.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.0.tgz#865ba3a9afc204ff2bdeea49dd64d58705007a39"
integrity sha512-/280MLdZe0W03stA69iL+v6I+J1ascrQ6FrXBlXGCsGzrfMaGr7fskMa0T5AhQIVQD4nA/46QQWxG//DYuFBcA==
"@next/swc-android-arm-eabi@12.1.2":
version "12.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.1.2.tgz#675e952d9032ac7bec02f3f413c17d33bbd90857"
integrity sha512-iwalfLBhYmCIlj09czFbovj1SmTycf0AGR8CB357wgmEN8xIuznIwSsCH87AhwQ9apfNtdeDhxvuKmhS9T3FqQ==
"@next/swc-darwin-arm64@12.1.0":
version "12.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.0.tgz#08e8b411b8accd095009ed12efbc2f1d4d547135"
integrity sha512-R8vcXE2/iONJ1Unf5Ptqjk6LRW3bggH+8drNkkzH4FLEQkHtELhvcmJwkXcuipyQCsIakldAXhRbZmm3YN1vXg==
"@next/swc-android-arm64@12.1.2":
version "12.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.2.tgz#d9710c50853235f258726b19a649df9c29a49682"
integrity sha512-ZoR0Vx7czJhTgRAcFbzTKQc2n2ChC036/uc6PbgYiI/LreEnfmsV/CiREP0pUVs5ndntOX8kBA3BSbh4zCO5tQ==
"@next/swc-darwin-x64@12.1.0":
version "12.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.0.tgz#fcd684497a76e8feaca88db3c394480ff0b007cd"
integrity sha512-ieAz0/J0PhmbZBB8+EA/JGdhRHBogF8BWaeqR7hwveb6SYEIJaDNQy0I+ZN8gF8hLj63bEDxJAs/cEhdnTq+ug==
"@next/swc-darwin-arm64@12.1.2":
version "12.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.2.tgz#aadd21b711c82b3efa9b4ecf7665841259e1fa7e"
integrity sha512-VXv7lpqFjHwkK65CZHkjvBxlSBTG+l3O0Zl2zHniHj0xHzxJZvR8VFjV2zIMZCYSfVqeQ5yt2rjwuQ9zbpGtXQ==
"@next/swc-linux-arm-gnueabihf@12.1.0":
version "12.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.0.tgz#9ec6380a27938a5799aaa6035c205b3c478468a7"
integrity sha512-njUd9hpl6o6A5d08dC0cKAgXKCzm5fFtgGe6i0eko8IAdtAPbtHxtpre3VeSxdZvuGFh+hb0REySQP9T1ttkog==
"@next/swc-darwin-x64@12.1.2":
version "12.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.2.tgz#3b1a389828f5c88ecb828a6394692fdeaf175081"
integrity sha512-evXxJQnXEnU+heWyun7d0UV6bhBcmoiyFGR3O3v9qdhGbeXh+SXYVxRO69juuh6V7RWRdlb1KQ0rGUNa1k0XSw==
"@next/swc-linux-arm64-gnu@12.1.0":
version "12.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.0.tgz#7f4196dff1049cea479607c75b81033ae2dbd093"
integrity sha512-OqangJLkRxVxMhDtcb7Qn1xjzFA3s50EIxY7mljbSCLybU+sByPaWAHY4px97ieOlr2y4S0xdPKkQ3BCAwyo6Q==
"@next/swc-linux-arm-gnueabihf@12.1.2":
version "12.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.2.tgz#db4371ca716bf94c94d4f6b001ac3c9d08d97d79"
integrity sha512-LJV/wo6R0Ot7Y/20bZs00aBG4J333RT6H/5Q2AROE4Hnx7cenSktSnfU6WCnJgzYLSIHdbLs549LcZMULuVquw==
"@next/swc-linux-arm64-musl@12.1.0":
version "12.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.0.tgz#b445f767569cdc2dddee785ca495e1a88c025566"
integrity sha512-hB8cLSt4GdmOpcwRe2UzI5UWn6HHO/vLkr5OTuNvCJ5xGDwpPXelVkYW/0+C3g5axbDW2Tym4S+MQCkkH9QfWA==
"@next/swc-linux-arm64-gnu@12.1.2":
version "12.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.2.tgz#0e71db03b8b12ed315c8be7d15392ecefe562b7c"
integrity sha512-fjlYU1Y8kVjjRKyuyQBYLHPxjGOS2ox7U8TqAvtgKvd2PxqdsgW4sP+VDovRVPrZlGXNllKoJiqMO1OoR9fB6w==
"@next/swc-linux-x64-gnu@12.1.0":
version "12.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.0.tgz#67610e9be4fbc987de7535f1bcb17e45fe12f90e"
integrity sha512-OKO4R/digvrVuweSw/uBM4nSdyzsBV5EwkUeeG4KVpkIZEe64ZwRpnFB65bC6hGwxIBnTv5NMSnJ+0K/WmG78A==
"@next/swc-linux-arm64-musl@12.1.2":
version "12.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.2.tgz#f1b055793da1c12167ed3b6e32aef8289721a1fb"
integrity sha512-Y1JRDMHqSjLObjyrD1hf6ePrJcOF/mkw+LbAzoNgrHL1dSuIAqcz3jYunJt8T7Yw48xSJy6LPSL9BclAHwEwOA==
"@next/swc-linux-x64-musl@12.1.0":
version "12.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.0.tgz#ea19a23db08a9f2e34ac30401f774cf7d1669d31"
integrity sha512-JohhgAHZvOD3rQY7tlp7NlmvtvYHBYgY0x5ZCecUT6eCCcl9lv6iV3nfu82ErkxNk1H893fqH0FUpznZ/H3pSw==
"@next/swc-linux-x64-gnu@12.1.2":
version "12.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.2.tgz#69764ffaacb3b9b373897fff15d7dd871455efe2"
integrity sha512-5N4QSRT60ikQqCU8iHfYZzlhg6MFTLsKhMTARmhn8wLtZfN9VVyTFwZrJQWjV64dZc4JFeXDANGao8fm55y6bw==
"@next/swc-win32-arm64-msvc@12.1.0":
version "12.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.0.tgz#eadf054fc412085659b98e145435bbba200b5283"
integrity sha512-T/3gIE6QEfKIJ4dmJk75v9hhNiYZhQYAoYm4iVo1TgcsuaKLFa+zMPh4056AHiG6n9tn2UQ1CFE8EoybEsqsSw==
"@next/swc-linux-x64-musl@12.1.2":
version "12.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.2.tgz#0ddaedb5ec578c01771f83be2046dafb2f70df91"
integrity sha512-b32F/xAgdYG4Pt0foFzhF+2uhvNxnEj7aJNp1R4EhZotdej2PzvFWcP/dGkc7MJl205pBz5oC3gHyILIIlW6XA==
"@next/swc-win32-ia32-msvc@12.1.0":
version "12.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.0.tgz#68faeae10c89f698bf9d28759172b74c9c21bda1"
integrity sha512-iwnKgHJdqhIW19H9PRPM9j55V6RdcOo6rX+5imx832BCWzkDbyomWnlzBfr6ByUYfhohb8QuH4hSGEikpPqI0Q==
"@next/swc-win32-arm64-msvc@12.1.2":
version "12.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.2.tgz#9e17ed56d5621f8c6961193da3a0b155cea511c9"
integrity sha512-hVOcGmWDeVwO00Aclopsj6MoYhfJl5zA4vjAai9KjgclQTFZa/DC0vQjgKAHHKGT5oMHgjiq/G7L6P1/UfwYnw==
"@next/swc-win32-x64-msvc@12.1.0":
version "12.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.0.tgz#d27e7e76c87a460a4da99c5bfdb1618dcd6cd064"
integrity sha512-aBvcbMwuanDH4EMrL2TthNJy+4nP59Bimn8egqv6GHMVj0a44cU6Au4PjOhLNqEh9l+IpRGBqMTzec94UdC5xg==
"@next/swc-win32-ia32-msvc@12.1.2":
version "12.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.2.tgz#ddd260cbe8bc4002fb54415b80baccf37f8db783"
integrity sha512-wnVDGIVz2pR3vIkyN6IE+1NvMSBrBj1jba11iR16m8TAPzZH/PrNsxr0a9N5VavEXXLcQpoUVvT+N7nflbRAHg==
"@next/swc-win32-x64-msvc@12.1.2":
version "12.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.2.tgz#37412a314bcf4c6006a74e1ef9764048344f3848"
integrity sha512-MLNcurEpQp0+7OU9261f7PkN52xTGkfrt4IYTIXau7DO/aHj927oK6piIJdl9EOHdX/KN5W6qlyErj170PSHtw==
"@polka/url@^1.0.0-next.20":
version "1.0.0-next.21"
@@ -2622,28 +2627,29 @@ next-mdx-remote@^4.0.0:
vfile "^5.3.0"
vfile-matter "^3.0.1"
next@^12.1.0:
version "12.1.0"
resolved "https://registry.yarnpkg.com/next/-/next-12.1.0.tgz#c33d753b644be92fc58e06e5a214f143da61dd5d"
integrity sha512-s885kWvnIlxsUFHq9UGyIyLiuD0G3BUC/xrH0CEnH5lHEWkwQcHOORgbDF0hbrW9vr/7am4ETfX4A7M6DjrE7Q==
next@^12.1.2:
version "12.1.2"
resolved "https://registry.yarnpkg.com/next/-/next-12.1.2.tgz#c5376a8ae17d3e404a2b691c01f94c8943306f29"
integrity sha512-JHPCsnFTBO0Z4SQxSYc611UA1WA+r/3y3Neg66AH5/gSO/oksfRnFw/zGX/FZ9+oOUHS9y3wJFawNpVYR2gJSQ==
dependencies:
"@next/env" "12.1.0"
"@next/env" "12.1.2"
caniuse-lite "^1.0.30001283"
postcss "8.4.5"
styled-jsx "5.0.0"
styled-jsx "5.0.1"
use-subscription "1.5.1"
optionalDependencies:
"@next/swc-android-arm64" "12.1.0"
"@next/swc-darwin-arm64" "12.1.0"
"@next/swc-darwin-x64" "12.1.0"
"@next/swc-linux-arm-gnueabihf" "12.1.0"
"@next/swc-linux-arm64-gnu" "12.1.0"
"@next/swc-linux-arm64-musl" "12.1.0"
"@next/swc-linux-x64-gnu" "12.1.0"
"@next/swc-linux-x64-musl" "12.1.0"
"@next/swc-win32-arm64-msvc" "12.1.0"
"@next/swc-win32-ia32-msvc" "12.1.0"
"@next/swc-win32-x64-msvc" "12.1.0"
"@next/swc-android-arm-eabi" "12.1.2"
"@next/swc-android-arm64" "12.1.2"
"@next/swc-darwin-arm64" "12.1.2"
"@next/swc-darwin-x64" "12.1.2"
"@next/swc-linux-arm-gnueabihf" "12.1.2"
"@next/swc-linux-arm64-gnu" "12.1.2"
"@next/swc-linux-arm64-musl" "12.1.2"
"@next/swc-linux-x64-gnu" "12.1.2"
"@next/swc-linux-x64-musl" "12.1.2"
"@next/swc-win32-arm64-msvc" "12.1.2"
"@next/swc-win32-ia32-msvc" "12.1.2"
"@next/swc-win32-x64-msvc" "12.1.2"
node-abi@^2.21.0:
version "2.30.1"
@@ -2965,7 +2971,7 @@ react-composer@^5.0.2:
dependencies:
prop-types "^15.6.0"
react-dom@^17.0.2:
react-dom@^17:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
@@ -3031,7 +3037,7 @@ react-use-measure@^2.1.1:
dependencies:
debounce "^1.2.1"
react@^17.0.2:
react@^17:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
@@ -3483,10 +3489,10 @@ styled-components@^5.3.3:
shallowequal "^1.1.0"
supports-color "^5.5.0"
styled-jsx@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.0.tgz#816b4b92e07b1786c6b7111821750e0ba4d26e77"
integrity sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA==
styled-jsx@5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.1.tgz#78fecbbad2bf95ce6cd981a08918ce4696f5fc80"
integrity sha512-+PIZ/6Uk40mphiQJJI1202b+/dYeTVd9ZnMPR80pgiWbjIwvN2zIp4r9et0BgqBuShh48I0gttPlAXA7WVvBxw==
supports-color@^5.3.0, supports-color@^5.5.0:
version "5.5.0"