postcss config, add typekit async loading

This commit is contained in:
Matthias Kretschmann 2019-10-20 19:59:22 +02:00
parent 444907ae0f
commit 090e907884
Signed by: m
GPG Key ID: 606EEEF3C479A91F
26 changed files with 161 additions and 137 deletions

View File

@ -1,36 +1,34 @@
{ {
"parser": "@typescript-eslint/parser", "extends": ["eslint:recommended", "prettier"],
"parserOptions": { "env": { "es6": true, "browser": true, "node": true },
"ecmaVersion": 2018, "settings": { "react": { "version": "detect" } },
"sourceType": "module", "overrides": [
"ecmaFeatures": { {
"jsx": true "files": ["**/*.ts", "**/*.tsx"],
}, "parser": "@typescript-eslint/parser",
"project": "./tsconfig.json", "parserOptions": {
"tsconfigRootDir": "./" "ecmaVersion": 2018,
}, "sourceType": "module",
"extends": [ "ecmaFeatures": {
"plugin:@typescript-eslint/eslint-recommended", "jsx": true
"plugin:@typescript-eslint/recommended", },
"plugin:jsx-a11y/recommended", "project": "./tsconfig.json",
"prettier/@typescript-eslint", "tsconfigRootDir": "./"
"prettier/react", },
"plugin:prettier/recommended", "extends": [
"plugin:react/recommended" "plugin:@typescript-eslint/eslint-recommended",
], "plugin:@typescript-eslint/recommended",
"plugins": ["@typescript-eslint", "react"], "plugin:jsx-a11y/recommended",
"rules": { "prettier/@typescript-eslint",
"react/prop-types": "off", "prettier/react",
"@typescript-eslint/explicit-function-return-type": "off" "plugin:prettier/recommended",
}, "plugin:react/recommended"
"env": { ],
"es6": true, "plugins": ["@typescript-eslint", "react"],
"browser": true, "rules": {
"jest": true "react/prop-types": "off",
}, "@typescript-eslint/explicit-function-return-type": "off"
"settings": { }
"react": {
"version": "detect"
} }
} ]
} }

6
.gitignore vendored
View File

@ -1,7 +1,7 @@
node_modules node_modules
npm-debug.log npm-debug.log
.DS_Store .DS_Store
/.next/ .next
/out/ out
/build build
package-lock.json package-lock.json

View File

@ -1,5 +1,6 @@
const withCSS = require('@zeit/next-css') const withCSS = require('@zeit/next-css')
// eslint-disable-next-line no-unused-vars
const withSvgr = (nextConfig = {}, nextComposePlugins = {}) => { const withSvgr = (nextConfig = {}, nextComposePlugins = {}) => {
return Object.assign({}, nextConfig, { return Object.assign({}, nextConfig, {
webpack(config, options) { webpack(config, options) {
@ -28,7 +29,6 @@ module.exports = withSvgr(
withCSS({ withCSS({
cssModules: true, cssModules: true,
cssLoaderOptions: { cssLoaderOptions: {
importLoaders: 1,
localIdentName: '[local]___[hash:base64:5]' localIdentName: '[local]___[hash:base64:5]'
} }
}) })

View File

@ -1,13 +1,13 @@
{ {
"name": "@kremalicious/ipfs", "name": "@kremalicious/ipfs",
"version": "1.0.0", "version": "1.0.0",
"description": "Public IPFS Node.", "description": "A public IPFS node.",
"scripts": { "scripts": {
"start": "next dev", "start": "next dev",
"build": "next build", "build": "next build",
"serve": "next start", "serve": "next start",
"test": "eslint --ignore-path .gitignore 'src/**/*.{ts,tsx}'", "test": "eslint --ignore-path .gitignore '**/*.{js,jsx,ts,tsx}'",
"format": "prettier ./src/**/*.{css,yml,js,jsx,ts,tsx,json} --write" "format": "prettier --ignore-path .gitignore '**/*.{css,yml,js,jsx,ts,tsx,json}' --write"
}, },
"author": "Matthias Kretschmann <m@kretschmann.io>", "author": "Matthias Kretschmann <m@kretschmann.io>",
"license": "MIT", "license": "MIT",
@ -29,15 +29,23 @@
"@types/react": "^16.9.9", "@types/react": "^16.9.9",
"@typescript-eslint/eslint-plugin": "^2.4.0", "@typescript-eslint/eslint-plugin": "^2.4.0",
"@typescript-eslint/parser": "^2.4.0", "@typescript-eslint/parser": "^2.4.0",
"cssnano": "^4.1.10",
"eslint": "^6.5.1", "eslint": "^6.5.1",
"eslint-config-prettier": "^6.4.0", "eslint-config-prettier": "^6.4.0",
"eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.1", "eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-react": "^7.16.0", "eslint-plugin-react": "^7.16.0",
"postcss-preset-env": "^6.7.0",
"prettier": "^1.18.2", "prettier": "^1.18.2",
"typescript": "^3.6.4" "typescript": "^3.6.4"
}, },
"engines": { "engines": {
"node": "10.x" "node": "10.x"
} },
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
} }

8
postcss.config.js Normal file
View File

@ -0,0 +1,8 @@
module.exports = {
plugins: {
'postcss-preset-env': {
importFrom: './src/styles/_variables.css'
},
cssnano: {}
}
}

View File

@ -3,5 +3,6 @@ module.exports = {
description: 'A public IPFS Gateway', description: 'A public IPFS Gateway',
url: 'https://ipfs.kretschmann.io', url: 'https://ipfs.kretschmann.io',
ipfsGateway: 'https://ipfs.kretschmann.io', ipfsGateway: 'https://ipfs.kretschmann.io',
ipfsNodeUri: 'https://ipfs.kretschmann.io:443' ipfsNodeUri: 'https://ipfs.kretschmann.io:443',
typekitId: 'msu4qap'
} }

5
src/@types/ipfs.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
export interface IpfsConfig {
protocol: string
host: string
port: string
}

View File

@ -1,5 +1,3 @@
@import './styles/_variables.css';
.app { .app {
padding: var(--spacer); padding: var(--spacer);
display: flex; display: flex;

View File

@ -1,9 +1,8 @@
import React, { ReactNode } from 'react' import React, { ReactNode } from 'react'
import Head from 'next/head'
import { NextSeo } from 'next-seo' import { NextSeo } from 'next-seo'
import Footer from './components/Footer' import Footer from './components/Footer'
import styles from './Layout.module.css'
import { title, description, url } from '../site.config' import { title, description, url } from '../site.config'
import styles from './Layout.module.css'
export default function Layout({ export default function Layout({
children, children,
@ -14,10 +13,6 @@ export default function Layout({
}) { }) {
return ( return (
<div className={styles.app}> <div className={styles.app}>
<Head>
<link rel="icon" href="/favicon.ico" />
</Head>
<NextSeo <NextSeo
title={pageTitle} title={pageTitle}
description={description} description={description}

View File

@ -1,5 +1,3 @@
@import '../styles/_variables.css';
.add { .add {
width: 100%; width: 100%;
overflow-wrap: break-word; overflow-wrap: break-word;

View File

@ -3,16 +3,9 @@ import { ipfsNodeUri, ipfsGateway } from '../../site.config'
import Dropzone from './Dropzone' import Dropzone from './Dropzone'
import styles from './Add.module.css' import styles from './Add.module.css'
import Loader from './Loader' import Loader from './Loader'
import useIpfsApi, { IpfsConfig } from '../hooks/use-ipfs-api' import useIpfsApi from '../hooks/use-ipfs-api'
import { IpfsConfig } from '../@types/ipfs'
export function formatBytes(a: number, b: number) { import { formatBytes, addToIpfs } from '../utils'
if (a === 0) return '0 Bytes'
const c = 1024
const d = b || 2
const e = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
const f = Math.floor(Math.log(a) / Math.log(c))
return parseFloat((a / Math.pow(c, f)).toFixed(d)) + ' ' + e[f]
}
const { hostname, port, protocol } = new URL(ipfsNodeUri) const { hostname, port, protocol } = new URL(ipfsNodeUri)
@ -22,24 +15,6 @@ const ipfsConfig: IpfsConfig = {
port: port || '443' port: port || '443'
} }
async function addToIpfs(
files: File[],
setFileSizeReceived: (size: string) => void,
ipfs: any
) {
const file = [...files][0]
const fileDetails = { path: file.name, content: file }
const response = await ipfs.add(fileDetails, {
wrapWithDirectory: true,
progress: (length: number) => setFileSizeReceived(formatBytes(length, 0))
})
// CID of wrapping directory is returned last
const cid = `${response[response.length - 1].hash}/${file.name}`
return cid
}
export default function Add() { export default function Add() {
const { ipfs, isIpfsReady, ipfsError } = useIpfsApi(ipfsConfig) const { ipfs, isIpfsReady, ipfsError } = useIpfsApi(ipfsConfig)
const [fileHash, setFileHash] = useState() const [fileHash, setFileHash] = useState()

View File

@ -1,15 +1,5 @@
@import '../styles/_variables.css';
:root {
--border-color: var(--brand-grey-dimmed);
}
:global(.dark) {
--border-color: var(--brand-grey);
}
.dropzone { .dropzone {
border: 0.4rem dashed var(--border-color); border: 0.4rem dashed var(--brand-grey-dimmed);
border-radius: var(--border-radius); border-radius: var(--border-radius);
padding: calc(var(--spacer) * 2) var(--spacer); padding: calc(var(--spacer) * 2) var(--spacer);
transition: 0.2s ease-out; transition: 0.2s ease-out;
@ -18,6 +8,10 @@
color: var(--brand-grey-light); color: var(--brand-grey-light);
} }
:global(.dark) .dropzone {
border-color: var(--brand-grey);
}
.dropzone:hover, .dropzone:hover,
.dropzone:focus, .dropzone:focus,
.dropzone:active { .dropzone:active {

View File

@ -1,5 +1,3 @@
@import '../styles/_variables.css';
.footer { .footer {
width: 100%; width: 100%;
font-size: var(--font-size-mini); font-size: var(--font-size-mini);

View File

@ -1,5 +1,3 @@
@import '../styles/_variables.css';
.info { .info {
font-size: var(--font-size-small); font-size: var(--font-size-small);
opacity: 0.8; opacity: 0.8;

View File

@ -1,5 +1,3 @@
@import '../styles/_variables.css';
.loader { .loader {
position: relative; position: relative;
text-align: center; text-align: center;
@ -10,17 +8,15 @@
.loader:before, .loader:before,
.loader:after { .loader:after {
--size: 1.75rem;
content: ''; content: '';
box-sizing: border-box; box-sizing: border-box;
position: absolute; position: absolute;
top: 0; top: 0;
left: 50%; left: 50%;
margin-top: calc(var(--size) * -1); margin-top: calc(var(--loaderSize) * -1);
margin-left: calc(var(--size) / -2); margin-left: calc(var(--loaderSize) / -2);
width: var(--size); width: var(--loaderSize);
height: var(--size); height: var(--loaderSize);
border-radius: 50%; border-radius: 50%;
background-color: var(--brand-cyan); background-color: var(--brand-cyan);
opacity: 0.6; opacity: 0.6;

View File

@ -1,5 +1,3 @@
@import '../styles/_variables.css';
/* default: red square */ /* default: red square */
.status { .status {
width: 0.5rem; width: 0.5rem;

View File

@ -1,10 +1,3 @@
@import '../styles/_variables.css';
:root {
--knob-size: 8px;
--knob-space: 1px;
}
.themeSwitch { .themeSwitch {
position: relative; position: relative;
display: inline-block; display: inline-block;
@ -33,8 +26,8 @@
.checkboxFake { .checkboxFake {
display: block; display: block;
position: relative; position: relative;
width: calc(var(--knob-size) * 2.5); width: calc(var(--switch-knob-size) * 2.5);
height: calc(var(--knob-size) + calc(var(--knob-space) * 4)); height: calc(var(--switch-knob-size) + calc(var(--switch-knob-space) * 4));
border: 1px solid var(--brand-grey-light); border: 1px solid var(--brand-grey-light);
border-radius: 15rem; border-radius: 15rem;
margin-left: calc(var(--spacer) / 3); margin-left: calc(var(--spacer) / 3);
@ -44,10 +37,10 @@
.checkboxFake::after { .checkboxFake::after {
content: ''; content: '';
position: absolute; position: absolute;
top: var(--knob-space); top: var(--switch-knob-space);
left: var(--knob-space); left: var(--switch-knob-space);
width: var(--knob-size); width: var(--switch-knob-size);
height: var(--knob-size); height: var(--switch-knob-size);
background-color: var(--brand-grey-light); background-color: var(--brand-grey-light);
border-radius: 15rem; border-radius: 15rem;
transition: transform 0.2s var(--easing); transition: transform 0.2s var(--easing);

View File

@ -0,0 +1,24 @@
import React from 'react'
import Head from 'next/head'
import { typekitId } from '../../site.config'
const typekitScript = `
(function(d) {
var config = {
kitId: '${typekitId}',
scriptTimeout: 3000,
async: true
},
h=d.documentElement,t=setTimeout(function(){h.className=h.className.replace(/\bwf-loading\b/g,"")+" wf-inactive";},config.scriptTimeout),tk=d.createElement("script"),f=false,s=d.getElementsByTagName("script")[0],a;h.className+=" wf-loading";tk.src='https://use.typekit.net/'+config.kitId+'.js';tk.async=true;tk.onload=tk.onreadystatechange=function(){a=this.readyState;if(f||a&&a!="complete"&&a!="loaded")return;f=true;clearTimeout(t);try{Typekit.load(config)}catch(e){}};s.parentNode.insertBefore(tk,s)
})(document);
`
export default function Typekit() {
return typekitId ? (
<Head key="typekit">
<link rel="dns-prefetch" href="https://use.typekit.net/" />
<link rel="dns-prefetch" href="https://p.typekit.net/" />
<script dangerouslySetInnerHTML={{ __html: typekitScript }} />
</Head>
) : null
}

View File

@ -1,21 +1,11 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import ipfsClient from 'ipfs-http-client' import ipfsClient from 'ipfs-http-client'
import { parseHTML } from '../utils'
import { IpfsConfig } from '../@types/ipfs'
let ipfs: any = null let ipfs: any = null
let ipfsVersion = '' let ipfsVersion = ''
export interface IpfsConfig {
protocol: string
host: string
port: string
}
function parseHTML(str: string) {
const tmp = document.implementation.createHTMLDocument()
tmp.body.innerHTML = str
return tmp.body.children
}
export default function useIpfsApi(config: IpfsConfig) { export default function useIpfsApi(config: IpfsConfig) {
const [isIpfsReady, setIpfsReady] = useState(Boolean(ipfs)) const [isIpfsReady, setIpfsReady] = useState(Boolean(ipfs))
const [ipfsError, setIpfsError] = useState('') const [ipfsError, setIpfsError] = useState('')

16
src/pages/_app.tsx Normal file
View File

@ -0,0 +1,16 @@
import '../styles/global.css'
import App from 'next/app'
import React from 'react'
import Typekit from '../components/Typekit'
export default class MyApp extends App {
render() {
const { Component, pageProps } = this.props
return (
<>
<Typekit />
<Component {...pageProps} />
</>
)
}
}

View File

@ -1,5 +1,3 @@
@import '../styles/_variables.css';
.header { .header {
margin-top: 10vh; margin-top: 10vh;
margin-bottom: calc(var(--spacer) * 3); margin-bottom: calc(var(--spacer) * 3);

View File

@ -1,7 +1,4 @@
import React from 'react' import React from 'react'
import '../styles/global.css'
import Add from '../components/Add' import Add from '../components/Add'
import { title, description } from '../../site.config' import { title, description } from '../../site.config'
import styles from './index.module.css' import styles from './index.module.css'

View File

@ -44,6 +44,10 @@
--easing: cubic-bezier(0.75, 0, 0.08, 1); --easing: cubic-bezier(0.75, 0, 0.08, 1);
--switch-knob-size: 8px;
--switch-knob-space: 1px;
--loaderSize: 1.75rem;
--body-background-color: var(--brand-light); --body-background-color: var(--brand-light);
--color-text: var(--brand-grey); --color-text: var(--brand-grey);
--color-headings: var(--brand-main); --color-headings: var(--brand-main);

View File

@ -1,5 +1,4 @@
@import '_variables.css'; @import '_variables.css';
@import url('https://use.typekit.net/msu4qap.css');
*, *,
*:before, *:before,

View File

@ -1,5 +1,32 @@
import axios from 'axios' import axios from 'axios'
export function formatBytes(a: number, b: number) {
if (a === 0) return '0 Bytes'
const c = 1024
const d = b || 2
const e = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
const f = Math.floor(Math.log(a) / Math.log(c))
return parseFloat((a / Math.pow(c, f)).toFixed(d)) + ' ' + e[f]
}
export async function addToIpfs(
files: File[],
setFileSizeReceived: (size: string) => void,
ipfs: any
) {
const file = [...files][0]
const fileDetails = { path: file.name, content: file }
const response = await ipfs.add(fileDetails, {
wrapWithDirectory: true,
progress: (length: number) => setFileSizeReceived(formatBytes(length, 0))
})
// CID of wrapping directory is returned last
const cid = `${response[response.length - 1].hash}/${file.name}`
return cid
}
export async function pingUrl(url: string) { export async function pingUrl(url: string) {
try { try {
const response = await axios(url, { timeout: 5000 }) const response = await axios(url, { timeout: 5000 })
@ -10,3 +37,9 @@ export async function pingUrl(url: string) {
return false return false
} }
} }
export function parseHTML(str: string) {
const tmp = document.implementation.createHTMLDocument()
tmp.body.innerHTML = str
return tmp.body.children
}

View File

@ -20,6 +20,6 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true "isolatedModules": true
}, },
"exclude": ["node_modules"], "exclude": ["node_modules", ".next"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.mdx"] "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.mdx"]
} }