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

6
.gitignore vendored
View File

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

View File

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

View File

@ -1,13 +1,13 @@
{
"name": "@kremalicious/ipfs",
"version": "1.0.0",
"description": "Public IPFS Node.",
"description": "A public IPFS node.",
"scripts": {
"start": "next dev",
"build": "next build",
"serve": "next start",
"test": "eslint --ignore-path .gitignore 'src/**/*.{ts,tsx}'",
"format": "prettier ./src/**/*.{css,yml,js,jsx,ts,tsx,json} --write"
"test": "eslint --ignore-path .gitignore '**/*.{js,jsx,ts,tsx}'",
"format": "prettier --ignore-path .gitignore '**/*.{css,yml,js,jsx,ts,tsx,json}' --write"
},
"author": "Matthias Kretschmann <m@kretschmann.io>",
"license": "MIT",
@ -29,15 +29,23 @@
"@types/react": "^16.9.9",
"@typescript-eslint/eslint-plugin": "^2.4.0",
"@typescript-eslint/parser": "^2.4.0",
"cssnano": "^4.1.10",
"eslint": "^6.5.1",
"eslint-config-prettier": "^6.4.0",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-react": "^7.16.0",
"postcss-preset-env": "^6.7.0",
"prettier": "^1.18.2",
"typescript": "^3.6.4"
},
"engines": {
"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',
url: '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 {
padding: var(--spacer);
display: flex;

View File

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

View File

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

View File

@ -3,16 +3,9 @@ import { ipfsNodeUri, ipfsGateway } from '../../site.config'
import Dropzone from './Dropzone'
import styles from './Add.module.css'
import Loader from './Loader'
import useIpfsApi, { IpfsConfig } from '../hooks/use-ipfs-api'
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]
}
import useIpfsApi from '../hooks/use-ipfs-api'
import { IpfsConfig } from '../@types/ipfs'
import { formatBytes, addToIpfs } from '../utils'
const { hostname, port, protocol } = new URL(ipfsNodeUri)
@ -22,24 +15,6 @@ const ipfsConfig: IpfsConfig = {
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() {
const { ipfs, isIpfsReady, ipfsError } = useIpfsApi(ipfsConfig)
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 {
border: 0.4rem dashed var(--border-color);
border: 0.4rem dashed var(--brand-grey-dimmed);
border-radius: var(--border-radius);
padding: calc(var(--spacer) * 2) var(--spacer);
transition: 0.2s ease-out;
@ -18,6 +8,10 @@
color: var(--brand-grey-light);
}
:global(.dark) .dropzone {
border-color: var(--brand-grey);
}
.dropzone:hover,
.dropzone:focus,
.dropzone:active {

View File

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

View File

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

View File

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

View File

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

View File

@ -1,10 +1,3 @@
@import '../styles/_variables.css';
:root {
--knob-size: 8px;
--knob-space: 1px;
}
.themeSwitch {
position: relative;
display: inline-block;
@ -33,8 +26,8 @@
.checkboxFake {
display: block;
position: relative;
width: calc(var(--knob-size) * 2.5);
height: calc(var(--knob-size) + calc(var(--knob-space) * 4));
width: calc(var(--switch-knob-size) * 2.5);
height: calc(var(--switch-knob-size) + calc(var(--switch-knob-space) * 4));
border: 1px solid var(--brand-grey-light);
border-radius: 15rem;
margin-left: calc(var(--spacer) / 3);
@ -44,10 +37,10 @@
.checkboxFake::after {
content: '';
position: absolute;
top: var(--knob-space);
left: var(--knob-space);
width: var(--knob-size);
height: var(--knob-size);
top: var(--switch-knob-space);
left: var(--switch-knob-space);
width: var(--switch-knob-size);
height: var(--switch-knob-size);
background-color: var(--brand-grey-light);
border-radius: 15rem;
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 ipfsClient from 'ipfs-http-client'
import { parseHTML } from '../utils'
import { IpfsConfig } from '../@types/ipfs'
let ipfs: any = null
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) {
const [isIpfsReady, setIpfsReady] = useState(Boolean(ipfs))
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 {
margin-top: 10vh;
margin-bottom: calc(var(--spacer) * 3);

View File

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

View File

@ -44,6 +44,10 @@
--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);
--color-text: var(--brand-grey);
--color-headings: var(--brand-main);

View File

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

View File

@ -1,5 +1,32 @@
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) {
try {
const response = await axios(url, { timeout: 5000 })
@ -10,3 +37,9 @@ export async function pingUrl(url: string) {
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,
"isolatedModules": true
},
"exclude": ["node_modules"],
"exclude": ["node_modules", ".next"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.mdx"]
}