Run Prettier across projects
Problem:
Prettier was not running when I saved Emacs buffers.
Why?
- prettier-js-mode needs needs node; lorri exposes node to direnv; direnv
  exposes node to Emacs; lorri was not working as expected.
Solution:
Now that I'm using nix-buffer, I can properly expose node (and other
dependencies) to my Emacs buffers. Now Prettier is working.
Commentary:
Since prettier hadn't worked for so long, I stopped thinking about it. As such,
I did not include it as a dependency in boilerplate/typescript. I added it
now. I retroactively ran prettier across a few of my frontend projects to unify
the code styling.
I may need to run...
```shell
$ cd ~/briefcase
$ nix-shell
$ npx prettier --list-different "**/*.{js,ts,jsx,tsx,html,css,json}"
```
...to see which files I should have formatted.
			
			
This commit is contained in:
		
							parent
							
								
									f4f7f454fa
								
							
						
					
					
						commit
						514136c99a
					
				
					 22 changed files with 181 additions and 128 deletions
				
			
		| 
						 | 
					@ -4,11 +4,13 @@
 | 
				
			||||||
  "main": "index.js",
 | 
					  "main": "index.js",
 | 
				
			||||||
  "license": "MIT",
 | 
					  "license": "MIT",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "dev": "npx parcel src/index.html & npx tsc --watch --noEmit"
 | 
					    "dev": "parcel src/index.html & npx tsc --watch --noEmit",
 | 
				
			||||||
 | 
					    "prettier": "prettier --ignore-path .gitignore --write \"**/*.{js,ts,jsx,tsx,html,css.json}\""
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@types/node": "^13.9.3",
 | 
					    "@types/node": "^13.9.3",
 | 
				
			||||||
    "parcel-bundler": "^1.12.4",
 | 
					    "parcel-bundler": "^1.12.4",
 | 
				
			||||||
 | 
					    "prettier": "^2.0.2",
 | 
				
			||||||
    "tailwindcss": "^1.2.0",
 | 
					    "tailwindcss": "^1.2.0",
 | 
				
			||||||
    "typescript": "^3.8.3"
 | 
					    "typescript": "^3.8.3"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,8 @@
 | 
				
			||||||
<!DOCTYPE html>
 | 
					<!DOCTYPE html>
 | 
				
			||||||
<html lang="en">
 | 
					<html lang="en">
 | 
				
			||||||
  <head>
 | 
					  <head>
 | 
				
			||||||
    <meta charset="UTF-8">
 | 
					    <meta charset="UTF-8" />
 | 
				
			||||||
    <link rel="stylesheet" href="./index.css">
 | 
					    <link rel="stylesheet" href="./index.css" />
 | 
				
			||||||
  </head>
 | 
					  </head>
 | 
				
			||||||
  <body>
 | 
					  <body>
 | 
				
			||||||
    <div id="mount"></div>
 | 
					    <div id="mount"></div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4287,6 +4287,11 @@ prelude-ls@~1.1.2:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
 | 
					  resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
 | 
				
			||||||
  integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
 | 
					  integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					prettier@^2.0.2:
 | 
				
			||||||
 | 
					  version "2.0.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.2.tgz#1ba8f3eb92231e769b7fcd7cb73ae1b6b74ade08"
 | 
				
			||||||
 | 
					  integrity sha512-5xJQIPT8BraI7ZnaDwSbu5zLrB6vvi8hVV58yHQ+QK64qrY40dULy0HSRlQ2/2IdzeBpjhDkqdcFBnFeDEMVdg==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pretty-hrtime@^1.0.3:
 | 
					pretty-hrtime@^1.0.3:
 | 
				
			||||||
  version "1.0.3"
 | 
					  version "1.0.3"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
 | 
					  resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								scratch/deepmind/part_two/package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								scratch/deepmind/part_two/package-lock.json
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -28,6 +28,12 @@
 | 
				
			||||||
      "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==",
 | 
					      "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "prettier": {
 | 
				
			||||||
 | 
					      "version": "2.0.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-5xJQIPT8BraI7ZnaDwSbu5zLrB6vvi8hVV58yHQ+QK64qrY40dULy0HSRlQ2/2IdzeBpjhDkqdcFBnFeDEMVdg==",
 | 
				
			||||||
 | 
					      "dev": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "source-map": {
 | 
					    "source-map": {
 | 
				
			||||||
      "version": "0.6.1",
 | 
					      "version": "0.6.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@
 | 
				
			||||||
  "author": "William Carroll",
 | 
					  "author": "William Carroll",
 | 
				
			||||||
  "license": "MIT",
 | 
					  "license": "MIT",
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "prettier": "^2.0.2",
 | 
				
			||||||
    "ts-node": "^8.6.2",
 | 
					    "ts-node": "^8.6.2",
 | 
				
			||||||
    "typescript": "^3.7.5"
 | 
					    "typescript": "^3.7.5"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ function sortScores(xs: Array<number>, highest: number): Array<number> {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (let i = 0; i < xs.length; i += 1) {
 | 
					  for (let i = 0; i < xs.length; i += 1) {
 | 
				
			||||||
    counts[xs[i]] += 1
 | 
					    counts[xs[i]] += 1;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (let i = highest; i >= 0; i -= 1) {
 | 
					  for (let i = highest; i >= 0; i -= 1) {
 | 
				
			||||||
| 
						 | 
					@ -22,29 +22,28 @@ function sortScores(xs: Array<number>, highest: number): Array<number> {
 | 
				
			||||||
  return result;
 | 
					  return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Tests
 | 
					// Tests
 | 
				
			||||||
let desc = 'no scores';
 | 
					let desc = "no scores";
 | 
				
			||||||
let actual = sortScores([], 100);
 | 
					let actual = sortScores([], 100);
 | 
				
			||||||
let expected = [];
 | 
					let expected = [];
 | 
				
			||||||
assertEqual(JSON.stringify(actual), JSON.stringify(expected), desc);
 | 
					assertEqual(JSON.stringify(actual), JSON.stringify(expected), desc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
desc = 'one score';
 | 
					desc = "one score";
 | 
				
			||||||
actual = sortScores([55], 100);
 | 
					actual = sortScores([55], 100);
 | 
				
			||||||
expected = [55];
 | 
					expected = [55];
 | 
				
			||||||
assertEqual(JSON.stringify(actual), JSON.stringify(expected), desc);
 | 
					assertEqual(JSON.stringify(actual), JSON.stringify(expected), desc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
desc = 'two scores';
 | 
					desc = "two scores";
 | 
				
			||||||
actual = sortScores([30, 60], 100);
 | 
					actual = sortScores([30, 60], 100);
 | 
				
			||||||
expected = [60, 30];
 | 
					expected = [60, 30];
 | 
				
			||||||
assertEqual(JSON.stringify(actual), JSON.stringify(expected), desc);
 | 
					assertEqual(JSON.stringify(actual), JSON.stringify(expected), desc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
desc = 'many scores';
 | 
					desc = "many scores";
 | 
				
			||||||
actual = sortScores([37, 89, 41, 65, 91, 53], 100);
 | 
					actual = sortScores([37, 89, 41, 65, 91, 53], 100);
 | 
				
			||||||
expected = [91, 89, 65, 53, 41, 37];
 | 
					expected = [91, 89, 65, 53, 41, 37];
 | 
				
			||||||
assertEqual(JSON.stringify(actual), JSON.stringify(expected), desc);
 | 
					assertEqual(JSON.stringify(actual), JSON.stringify(expected), desc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
desc = 'repeated scores';
 | 
					desc = "repeated scores";
 | 
				
			||||||
actual = sortScores([20, 10, 30, 30, 10, 20], 100);
 | 
					actual = sortScores([20, 10, 30, 30, 10, 20], 100);
 | 
				
			||||||
expected = [30, 30, 20, 20, 10, 10];
 | 
					expected = [30, 30, 20, 20, 10, 10];
 | 
				
			||||||
assertEqual(JSON.stringify(actual), JSON.stringify(expected), desc);
 | 
					assertEqual(JSON.stringify(actual), JSON.stringify(expected), desc);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,11 +4,13 @@
 | 
				
			||||||
  "main": "index.js",
 | 
					  "main": "index.js",
 | 
				
			||||||
  "license": "MIT",
 | 
					  "license": "MIT",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "dev": "npx parcel src/index.html & npx tsc --watch --noEmit"
 | 
					    "dev": "parcel src/index.html & npx tsc --watch --noEmit",
 | 
				
			||||||
 | 
					    "prettier": "prettier --ignore-path .gitignore --write \"**/*.{js,ts,jsx,tsx,html,css.json}\""
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@types/node": "^13.9.3",
 | 
					    "@types/node": "^13.9.3",
 | 
				
			||||||
    "parcel-bundler": "^1.12.4",
 | 
					    "parcel-bundler": "^1.12.4",
 | 
				
			||||||
 | 
					    "prettier": "^2.0.2",
 | 
				
			||||||
    "tailwindcss": "^1.2.0",
 | 
					    "tailwindcss": "^1.2.0",
 | 
				
			||||||
    "typescript": "^3.8.3"
 | 
					    "typescript": "^3.8.3"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,5 @@
 | 
				
			||||||
const tailwindcss = require('tailwindcss')
 | 
					const tailwindcss = require("tailwindcss");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
  plugins: [
 | 
					  plugins: [tailwindcss("./tailwind.config.js")],
 | 
				
			||||||
    tailwindcss('./tailwind.config.js')
 | 
					};
 | 
				
			||||||
  ]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,74 +1,84 @@
 | 
				
			||||||
import React from "react";
 | 
					import React from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function ProgressBar(props: {
 | 
					function ProgressBar(props: {
 | 
				
			||||||
  done: number,
 | 
					  done: number;
 | 
				
			||||||
  total: number,
 | 
					  total: number;
 | 
				
			||||||
  units: string,
 | 
					  units: string;
 | 
				
			||||||
  color: string,
 | 
					  color: string;
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
  const { done, total, units, color } = props
 | 
					  const { done, total, units, color } = props;
 | 
				
			||||||
  const width = Math.floor(done / total * 100)
 | 
					  const width = Math.floor((done / total) * 100);
 | 
				
			||||||
  const rest = 100 - width
 | 
					  const rest = 100 - width;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let [fg, bg] = [`bg-${color}-600`, `bg-${color}-100`]
 | 
					  let [fg, bg] = [`bg-${color}-600`, `bg-${color}-100`];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (color === 'white') {
 | 
					  if (color === "white") {
 | 
				
			||||||
    [fg, bg] = ['bg-gray-600', 'bg-gray-100']
 | 
					    [fg, bg] = ["bg-gray-600", "bg-gray-100"];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className={`relative ${bg} h-5`}>
 | 
					    <div className={`relative ${bg} h-5`}>
 | 
				
			||||||
      <div className={`${fg} h-5 absolute top-0 left-0`} style={{width: `${width}%`}}></div>
 | 
					      <div
 | 
				
			||||||
      <p className="absolute text-xs pl-1 pt-1">{done} of {total} {units}</p>
 | 
					        className={`${fg} h-5 absolute top-0 left-0`}
 | 
				
			||||||
 | 
					        style={{ width: `${width}%` }}
 | 
				
			||||||
 | 
					      ></div>
 | 
				
			||||||
 | 
					      <p className="absolute text-xs pl-1 pt-1">
 | 
				
			||||||
 | 
					        {done} of {total} {units}
 | 
				
			||||||
 | 
					      </p>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  )
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function Goal(props: {
 | 
					function Goal(props: {
 | 
				
			||||||
  subject: string,
 | 
					  subject: string;
 | 
				
			||||||
  goal: string,
 | 
					  goal: string;
 | 
				
			||||||
  done: number,
 | 
					  done: number;
 | 
				
			||||||
  total: number,
 | 
					  total: number;
 | 
				
			||||||
  units: string,
 | 
					  units: string;
 | 
				
			||||||
  color: string,
 | 
					  color: string;
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
  const { subject, goal, done, total, units, color } = props
 | 
					  const { subject, goal, done, total, units, color } = props;
 | 
				
			||||||
  const width = "6em"
 | 
					  const width = "6em";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const Tr = (props: {
 | 
					  const Tr = (props: {
 | 
				
			||||||
    label: string,
 | 
					    label: string;
 | 
				
			||||||
    value: string,
 | 
					    value: string;
 | 
				
			||||||
    valueComponent?: React.ReactElement,
 | 
					    valueComponent?: React.ReactElement;
 | 
				
			||||||
  }) => (
 | 
					  }) => (
 | 
				
			||||||
    <tr className="flex py-2">
 | 
					    <tr className="flex py-2">
 | 
				
			||||||
      <td className="text-gray-600" style={{width: width}}>{props.label}</td>
 | 
					      <td className="text-gray-600" style={{ width: width }}>
 | 
				
			||||||
 | 
					        {props.label}
 | 
				
			||||||
 | 
					      </td>
 | 
				
			||||||
      <td className="flex-1">
 | 
					      <td className="flex-1">
 | 
				
			||||||
        {props.valueComponent ? props.valueComponent : props.value}
 | 
					        {props.valueComponent ? props.valueComponent : props.value}
 | 
				
			||||||
      </td>
 | 
					      </td>
 | 
				
			||||||
    </tr>
 | 
					    </tr>
 | 
				
			||||||
  )
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <table className="w-full mb-10">
 | 
					    <table className="w-full mb-10">
 | 
				
			||||||
      <tbody>
 | 
					      <tbody>
 | 
				
			||||||
        <Tr label="Subject" value={subject} />
 | 
					        <Tr label="Subject" value={subject} />
 | 
				
			||||||
        <Tr label="Goal" value={goal} />
 | 
					        <Tr label="Goal" value={goal} />
 | 
				
			||||||
        <Tr label="Progress" value={goal} valueComponent={
 | 
					        <Tr
 | 
				
			||||||
          <ProgressBar done={done} total={total} units={units} color={color} />
 | 
					          label="Progress"
 | 
				
			||||||
        }/>
 | 
					          value={goal}
 | 
				
			||||||
 | 
					          valueComponent={
 | 
				
			||||||
 | 
					            <ProgressBar
 | 
				
			||||||
 | 
					              done={done}
 | 
				
			||||||
 | 
					              total={total}
 | 
				
			||||||
 | 
					              units={units}
 | 
				
			||||||
 | 
					              color={color}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
      </tbody>
 | 
					      </tbody>
 | 
				
			||||||
    </table>
 | 
					    </table>
 | 
				
			||||||
  )
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function Copy(props: {
 | 
					function Copy(props: { children: React.ReactNode }) {
 | 
				
			||||||
  children: React.ReactNode
 | 
					  return <p className="pb-4 leading-loose">{props.children}</p>;
 | 
				
			||||||
}) {
 | 
					 | 
				
			||||||
  return (
 | 
					 | 
				
			||||||
    <p className="pb-4 leading-loose">
 | 
					 | 
				
			||||||
      {props.children}
 | 
					 | 
				
			||||||
    </p>
 | 
					 | 
				
			||||||
  )
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function App() {
 | 
					function App() {
 | 
				
			||||||
| 
						 | 
					@ -90,27 +100,33 @@ function App() {
 | 
				
			||||||
        </Copy>
 | 
					        </Copy>
 | 
				
			||||||
      </section>
 | 
					      </section>
 | 
				
			||||||
      <section className="pt-4">
 | 
					      <section className="pt-4">
 | 
				
			||||||
        <Goal subject="Meditation"
 | 
					        <Goal
 | 
				
			||||||
 | 
					          subject="Meditation"
 | 
				
			||||||
          goal="Meditate for 10,000 hours"
 | 
					          goal="Meditate for 10,000 hours"
 | 
				
			||||||
          done={100}
 | 
					          done={100}
 | 
				
			||||||
          total={10000}
 | 
					          total={10000}
 | 
				
			||||||
          units="hrs"
 | 
					          units="hrs"
 | 
				
			||||||
              color="purple" />
 | 
					          color="purple"
 | 
				
			||||||
        <Goal subject="Debt"
 | 
					        />
 | 
				
			||||||
 | 
					        <Goal
 | 
				
			||||||
 | 
					          subject="Debt"
 | 
				
			||||||
          goal="Pay my student debt balance"
 | 
					          goal="Pay my student debt balance"
 | 
				
			||||||
          done={30000}
 | 
					          done={30000}
 | 
				
			||||||
          total={70000}
 | 
					          total={70000}
 | 
				
			||||||
          units="USD"
 | 
					          units="USD"
 | 
				
			||||||
              color="green" />
 | 
					          color="green"
 | 
				
			||||||
        <Goal subject="Brazilian Jiu Jitsu"
 | 
					        />
 | 
				
			||||||
 | 
					        <Goal
 | 
				
			||||||
 | 
					          subject="Brazilian Jiu Jitsu"
 | 
				
			||||||
          goal="Train until an instructor gives me a black belt"
 | 
					          goal="Train until an instructor gives me a black belt"
 | 
				
			||||||
          done={1}
 | 
					          done={1}
 | 
				
			||||||
          total={5}
 | 
					          total={5}
 | 
				
			||||||
          units="belts"
 | 
					          units="belts"
 | 
				
			||||||
              color="white" />
 | 
					          color="white"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
      </section>
 | 
					      </section>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  )
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default App;
 | 
					export default App;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,8 @@
 | 
				
			||||||
<!DOCTYPE html>
 | 
					<!DOCTYPE html>
 | 
				
			||||||
<html lang="en">
 | 
					<html lang="en">
 | 
				
			||||||
  <head>
 | 
					  <head>
 | 
				
			||||||
    <meta charset="UTF-8">
 | 
					    <meta charset="UTF-8" />
 | 
				
			||||||
    <link rel="stylesheet" href="./index.css">
 | 
					    <link rel="stylesheet" href="./index.css" />
 | 
				
			||||||
  </head>
 | 
					  </head>
 | 
				
			||||||
  <body>
 | 
					  <body>
 | 
				
			||||||
    <div id="mount"></div>
 | 
					    <div id="mount"></div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,4 +4,4 @@ module.exports = {
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  variants: {},
 | 
					  variants: {},
 | 
				
			||||||
  plugins: [],
 | 
					  plugins: [],
 | 
				
			||||||
}
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,7 @@
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  "compilerOptions": {
 | 
					  "compilerOptions": {
 | 
				
			||||||
    "target": "es5",
 | 
					    "target": "es5",
 | 
				
			||||||
    "lib": [
 | 
					    "lib": ["dom", "dom.iterable", "esnext"],
 | 
				
			||||||
      "dom",
 | 
					 | 
				
			||||||
      "dom.iterable",
 | 
					 | 
				
			||||||
      "esnext"
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    "allowJs": true,
 | 
					    "allowJs": true,
 | 
				
			||||||
    "skipLibCheck": true,
 | 
					    "skipLibCheck": true,
 | 
				
			||||||
    "esModuleInterop": true,
 | 
					    "esModuleInterop": true,
 | 
				
			||||||
| 
						 | 
					@ -19,7 +15,5 @@
 | 
				
			||||||
    "noEmit": true,
 | 
					    "noEmit": true,
 | 
				
			||||||
    "jsx": "react"
 | 
					    "jsx": "react"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "include": [
 | 
					  "include": ["src/**/*"]
 | 
				
			||||||
    "src/**/*"
 | 
					 | 
				
			||||||
  ]
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4287,6 +4287,11 @@ prelude-ls@~1.1.2:
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
 | 
					  resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
 | 
				
			||||||
  integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
 | 
					  integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					prettier@^2.0.2:
 | 
				
			||||||
 | 
					  version "2.0.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.2.tgz#1ba8f3eb92231e769b7fcd7cb73ae1b6b74ade08"
 | 
				
			||||||
 | 
					  integrity sha512-5xJQIPT8BraI7ZnaDwSbu5zLrB6vvi8hVV58yHQ+QK64qrY40dULy0HSRlQ2/2IdzeBpjhDkqdcFBnFeDEMVdg==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pretty-hrtime@^1.0.3:
 | 
					pretty-hrtime@^1.0.3:
 | 
				
			||||||
  version "1.0.3"
 | 
					  version "1.0.3"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
 | 
					  resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,10 @@
 | 
				
			||||||
    <meta charset="utf-8" />
 | 
					    <meta charset="utf-8" />
 | 
				
			||||||
    <meta name="viewport" content="width=device-width, initial-scale=1" />
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1" />
 | 
				
			||||||
    <meta name="description" content="Learn to code" />
 | 
					    <meta name="description" content="Learn to code" />
 | 
				
			||||||
    <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
 | 
					    <link
 | 
				
			||||||
 | 
					      href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css"
 | 
				
			||||||
 | 
					      rel="stylesheet"
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
    <title>Learn to code</title>
 | 
					    <title>Learn to code</title>
 | 
				
			||||||
  </head>
 | 
					  </head>
 | 
				
			||||||
  <body class="font-serif container max-w-2xl mx-auto px-8">
 | 
					  <body class="font-serif container max-w-2xl mx-auto px-8">
 | 
				
			||||||
| 
						 | 
					@ -42,33 +45,58 @@
 | 
				
			||||||
      <h2 class="text-3xl">Pricing</h2>
 | 
					      <h2 class="text-3xl">Pricing</h2>
 | 
				
			||||||
      <p class="leading-relaxed mb-4">
 | 
					      <p class="leading-relaxed mb-4">
 | 
				
			||||||
        I charge <bold class="font-bold">£50</bold> per hour for video lessons
 | 
					        I charge <bold class="font-bold">£50</bold> per hour for video lessons
 | 
				
			||||||
        and <bold class="font-bold">£100</bold> per hour for in-person
 | 
					        and <bold class="font-bold">£100</bold> per hour for in-person sessions.
 | 
				
			||||||
        sessions. I am currently based in South Kensington, London.
 | 
					        I am currently based in South Kensington, London.
 | 
				
			||||||
      </p>
 | 
					      </p>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="my-4">
 | 
					    <div class="my-4">
 | 
				
			||||||
      <h2 class="text-3xl">Contact</h2>
 | 
					      <h2 class="text-3xl">Contact</h2>
 | 
				
			||||||
      <p class="leading-relaxed mb-4">
 | 
					      <p class="leading-relaxed mb-4">
 | 
				
			||||||
        Whether you want to sign-up or simply want to learn more, send me an
 | 
					        Whether you want to sign-up or simply want to learn more, send me an
 | 
				
			||||||
        email at <a href="mailto:wpcarro@gmail.com" class="font-bold text-blue-600 hover:underline">wpcarro@gmail.com</a>.
 | 
					        email at
 | 
				
			||||||
 | 
					        <a
 | 
				
			||||||
 | 
					          href="mailto:wpcarro@gmail.com"
 | 
				
			||||||
 | 
					          class="font-bold text-blue-600 hover:underline"
 | 
				
			||||||
 | 
					          >wpcarro@gmail.com</a
 | 
				
			||||||
 | 
					        >.
 | 
				
			||||||
      </p>
 | 
					      </p>
 | 
				
			||||||
      <p class="text-center my-8">Why delay? <em>Start today.</em></p>
 | 
					      <p class="text-center my-8">Why delay? <em>Start today.</em></p>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <footer class="mb-8 lg:flex">
 | 
					    <footer class="mb-8 lg:flex">
 | 
				
			||||||
      <a class="block py-2 lg:w-1/4 text-center hover:underline" href="https://blog.wpcarro.dev">Blog</a>
 | 
					      <a
 | 
				
			||||||
      <a class="block py-2 lg:w-1/4 text-center hover:underline" href="https://linkedin.com/in/williampatrickcarroll">LinkedIn</a>
 | 
					        class="block py-2 lg:w-1/4 text-center hover:underline"
 | 
				
			||||||
      <a class="block py-2 lg:w-1/4 text-center hover:underline" href="https://twitter.com/wpcarro">Twitter</a>
 | 
					        href="https://blog.wpcarro.dev"
 | 
				
			||||||
      <a class="block py-2 lg:w-1/4 text-center hover:underline" href="https://github.com/wpcarro">Github</a>
 | 
					        >Blog</a
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					      <a
 | 
				
			||||||
 | 
					        class="block py-2 lg:w-1/4 text-center hover:underline"
 | 
				
			||||||
 | 
					        href="https://linkedin.com/in/williampatrickcarroll"
 | 
				
			||||||
 | 
					        >LinkedIn</a
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					      <a
 | 
				
			||||||
 | 
					        class="block py-2 lg:w-1/4 text-center hover:underline"
 | 
				
			||||||
 | 
					        href="https://twitter.com/wpcarro"
 | 
				
			||||||
 | 
					        >Twitter</a
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					      <a
 | 
				
			||||||
 | 
					        class="block py-2 lg:w-1/4 text-center hover:underline"
 | 
				
			||||||
 | 
					        href="https://github.com/wpcarro"
 | 
				
			||||||
 | 
					        >Github</a
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
    </footer>
 | 
					    </footer>
 | 
				
			||||||
    <!-- Global site tag (gtag.js) - Google Analytics -->
 | 
					    <!-- Global site tag (gtag.js) - Google Analytics -->
 | 
				
			||||||
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-160226702-1">
 | 
					    <script
 | 
				
			||||||
    </script>
 | 
					      async
 | 
				
			||||||
 | 
					      src="https://www.googletagmanager.com/gtag/js?id=UA-160226702-1"
 | 
				
			||||||
 | 
					    ></script>
 | 
				
			||||||
    <script>
 | 
					    <script>
 | 
				
			||||||
      window.dataLayer = window.dataLayer || [];
 | 
					      window.dataLayer = window.dataLayer || [];
 | 
				
			||||||
     function gtag(){dataLayer.push(arguments);}
 | 
					      function gtag() {
 | 
				
			||||||
     gtag('js', new Date());
 | 
					        dataLayer.push(arguments);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      gtag("js", new Date());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     gtag('config', 'UA-160226702-1');
 | 
					      gtag("config", "UA-160226702-1");
 | 
				
			||||||
    </script>
 | 
					    </script>
 | 
				
			||||||
  </body>
 | 
					  </body>
 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,5 @@
 | 
				
			||||||
const tailwindcss = require('tailwindcss')
 | 
					const tailwindcss = require("tailwindcss");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
  plugins: [
 | 
					  plugins: [tailwindcss("./tailwind.config.js")],
 | 
				
			||||||
    tailwindcss('./tailwind.config.js')
 | 
					};
 | 
				
			||||||
  ]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ import type { Book } from "./store";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const App: React.FC = () => {
 | 
					const App: React.FC = () => {
 | 
				
			||||||
  const dispatch = useDispatch();
 | 
					  const dispatch = useDispatch();
 | 
				
			||||||
  const { isLoading, books } = useTypedSelector(state => ({
 | 
					  const { isLoading, books } = useTypedSelector((state) => ({
 | 
				
			||||||
    isLoading: state.isLoading,
 | 
					    isLoading: state.isLoading,
 | 
				
			||||||
    books: state.books,
 | 
					    books: state.books,
 | 
				
			||||||
  }));
 | 
					  }));
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ const App: React.FC = () => {
 | 
				
			||||||
  useEffect(() => {
 | 
					  useEffect(() => {
 | 
				
			||||||
    async function fetchData() {
 | 
					    async function fetchData() {
 | 
				
			||||||
      const entries = await getClient().getEntries();
 | 
					      const entries = await getClient().getEntries();
 | 
				
			||||||
      const books = entries.items.map(x => x.fields) as Book[];
 | 
					      const books = entries.items.map((x) => x.fields) as Book[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      dispatch(actions.setBooks(books));
 | 
					      dispatch(actions.setBooks(books));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -30,9 +30,12 @@ const App: React.FC = () => {
 | 
				
			||||||
          <div className="container mx-auto">
 | 
					          <div className="container mx-auto">
 | 
				
			||||||
            <h1 className="py-6 text-2xl">Books</h1>
 | 
					            <h1 className="py-6 text-2xl">Books</h1>
 | 
				
			||||||
            <ul>
 | 
					            <ul>
 | 
				
			||||||
              {books.map(book => (
 | 
					              {books.map((book) => (
 | 
				
			||||||
                <li key={book.title} className="py-3">
 | 
					                <li key={book.title} className="py-3">
 | 
				
			||||||
                  <p><span className="font-bold pr-3">{book.title}</span><span className="text-gray-600">{book.author}</span></p>
 | 
					                  <p>
 | 
				
			||||||
 | 
					                    <span className="font-bold pr-3">{book.title}</span>
 | 
				
			||||||
 | 
					                    <span className="text-gray-600">{book.author}</span>
 | 
				
			||||||
 | 
					                  </p>
 | 
				
			||||||
                </li>
 | 
					                </li>
 | 
				
			||||||
              ))}
 | 
					              ))}
 | 
				
			||||||
            </ul>
 | 
					            </ul>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,10 +8,10 @@ let client: ContentfulClientApi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Idempotent way to get a reference to the Contentful client.
 | 
					// Idempotent way to get a reference to the Contentful client.
 | 
				
			||||||
export const getClient = (): ContentfulClientApi => {
 | 
					export const getClient = (): ContentfulClientApi => {
 | 
				
			||||||
  if (typeof client !== 'undefined') {
 | 
					  if (typeof client !== "undefined") {
 | 
				
			||||||
    return client;
 | 
					    return client;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    if (typeof space === 'string' && typeof accessToken === 'string') {
 | 
					    if (typeof space === "string" && typeof accessToken === "string") {
 | 
				
			||||||
      let client = createClient({
 | 
					      let client = createClient({
 | 
				
			||||||
        space,
 | 
					        space,
 | 
				
			||||||
        accessToken,
 | 
					        accessToken,
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,9 @@ export const getClient = (): ContentfulClientApi => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return client;
 | 
					      return client;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      throw new Error('Please set CONTENTFUL_SPACE_ID and CONTENTFUL_ACCESS_TOKEN');
 | 
					      throw new Error(
 | 
				
			||||||
    }
 | 
					        "Please set CONTENTFUL_SPACE_ID and CONTENTFUL_ACCESS_TOKEN"
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,8 @@
 | 
				
			||||||
<!DOCTYPE html>
 | 
					<!DOCTYPE html>
 | 
				
			||||||
<html lang="en">
 | 
					<html lang="en">
 | 
				
			||||||
  <head>
 | 
					  <head>
 | 
				
			||||||
    <meta charset="UTF-8">
 | 
					    <meta charset="UTF-8" />
 | 
				
			||||||
    <link rel="stylesheet" href="./index.css">
 | 
					    <link rel="stylesheet" href="./index.css" />
 | 
				
			||||||
  </head>
 | 
					  </head>
 | 
				
			||||||
  <body>
 | 
					  <body>
 | 
				
			||||||
    <div id="mount"></div>
 | 
					    <div id="mount"></div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,9 +22,9 @@ export const { actions, reducer } = createSlice({
 | 
				
			||||||
  name: "application",
 | 
					  name: "application",
 | 
				
			||||||
  initialState,
 | 
					  initialState,
 | 
				
			||||||
  reducers: {
 | 
					  reducers: {
 | 
				
			||||||
    toggleIsLoading: state => ({ ...state, isLoading: !state.isLoading }),
 | 
					    toggleIsLoading: (state) => ({ ...state, isLoading: !state.isLoading }),
 | 
				
			||||||
    setBooks: (state, action) => ({ ...state, books: action.payload }),
 | 
					    setBooks: (state, action) => ({ ...state, books: action.payload }),
 | 
				
			||||||
  }
 | 
					  },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,4 +4,4 @@ module.exports = {
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  variants: {},
 | 
					  variants: {},
 | 
				
			||||||
  plugins: [],
 | 
					  plugins: [],
 | 
				
			||||||
}
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,7 @@
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  "compilerOptions": {
 | 
					  "compilerOptions": {
 | 
				
			||||||
    "target": "es5",
 | 
					    "target": "es5",
 | 
				
			||||||
    "lib": [
 | 
					    "lib": ["dom", "dom.iterable", "esnext"],
 | 
				
			||||||
      "dom",
 | 
					 | 
				
			||||||
      "dom.iterable",
 | 
					 | 
				
			||||||
      "esnext"
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    "allowJs": true,
 | 
					    "allowJs": true,
 | 
				
			||||||
    "skipLibCheck": true,
 | 
					    "skipLibCheck": true,
 | 
				
			||||||
    "esModuleInterop": true,
 | 
					    "esModuleInterop": true,
 | 
				
			||||||
| 
						 | 
					@ -19,7 +15,5 @@
 | 
				
			||||||
    "noEmit": true,
 | 
					    "noEmit": true,
 | 
				
			||||||
    "jsx": "react"
 | 
					    "jsx": "react"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "include": [
 | 
					  "include": ["src/**/*"]
 | 
				
			||||||
    "src/**/*"
 | 
					 | 
				
			||||||
  ]
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
<!DOCTYPE html>
 | 
					<!DOCTYPE html>
 | 
				
			||||||
<html lang="en">
 | 
					<html lang="en">
 | 
				
			||||||
  <head>
 | 
					  <head>
 | 
				
			||||||
    <meta charset="UTF-8">
 | 
					    <meta charset="UTF-8" />
 | 
				
			||||||
    <title>sandbox.wpcarro.dev</title>
 | 
					    <title>sandbox.wpcarro.dev</title>
 | 
				
			||||||
  </head>
 | 
					  </head>
 | 
				
			||||||
  <body>
 | 
					  <body>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue