From bd34d001f5fde117a06a47b926f064e6b329fea1 Mon Sep 17 00:00:00 2001 From: Shu Uesugi Date: Sun, 17 Nov 2019 11:07:20 -0800 Subject: [PATCH 1/3] Snippets support --- .prettierrc | 10 ++++- package.json | 7 ++- snippets/.eslintrc.js | 9 ++++ snippets/bin/generateSnippetsBundle.ts | 20 +++++++++ snippets/snippets/generics/cupt.ts | 20 +++++++++ snippets/snippets/generics/kiyi.ts | 5 +++ snippets/tsconfig.json | 3 ++ src/components/CodeBlock.tsx | 6 +-- src/lib/snippets.ts | 26 ++++++++++++ src/pages/generics.tsx | 7 +-- tsconfig.snippets.json | 10 +++++ yarn.lock | 59 +++++++++++++++++++++++++- 12 files changed, 170 insertions(+), 12 deletions(-) create mode 100644 snippets/.eslintrc.js create mode 100644 snippets/bin/generateSnippetsBundle.ts create mode 100644 snippets/snippets/generics/cupt.ts create mode 100644 snippets/snippets/generics/kiyi.ts create mode 100644 snippets/tsconfig.json create mode 100644 src/lib/snippets.ts create mode 100644 tsconfig.snippets.json diff --git a/.prettierrc b/.prettierrc index b2095be..494de5f 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,12 @@ { "semi": false, - "singleQuote": true + "singleQuote": true, + "overrides": [ + { + "files": "snippets/snippets/**/*.ts", + "options": { + "printWidth": 45 + } + } + ] } diff --git a/package.json b/package.json index 155ad97..694a4ae 100644 --- a/package.json +++ b/package.json @@ -18,13 +18,16 @@ "build": "next build && next export", "start": "next start", "tsc": "tsc", + "ts-node": "ts-node", "eslint": "eslint --ext .js,.ts,.tsx .", "eslint:fix": "eslint --ext .js,.ts,.tsx --fix .", - "svgr": "svgr --ext tsx --no-svgo --no-dimensions -d ." + "svgr": "svgr --ext tsx --no-svgo --no-dimensions -d .", + "snippets": "ts-node --project tsconfig.snippets.json snippets/bin/generateSnippetsBundle.ts" }, "devDependencies": { "@svgr/cli": "^4.3.3", "@types/color": "^3.0.0", + "@types/glob": "^7.1.1", "@types/luxon": "^1.15.2", "@types/node": "^12.12.7", "@types/prettier": "^1.18.3", @@ -40,7 +43,9 @@ "eslint-plugin-prettier": "^3.1.1", "eslint-plugin-react": "^7.16.0", "eslint-plugin-react-hooks": "2.2.0", + "glob": "^7.1.6", "prettier": "^1.19.1", + "ts-node": "^8.5.2", "typescript": "^3.7.2" } } diff --git a/snippets/.eslintrc.js b/snippets/.eslintrc.js new file mode 100644 index 0000000..8fd5c4f --- /dev/null +++ b/snippets/.eslintrc.js @@ -0,0 +1,9 @@ +const config = require('../.eslintrc') + +module.exports = { + ...config, + parserOptions: { + project: './snippets/tsconfig.json' + }, + root: true +} diff --git a/snippets/bin/generateSnippetsBundle.ts b/snippets/bin/generateSnippetsBundle.ts new file mode 100644 index 0000000..598c305 --- /dev/null +++ b/snippets/bin/generateSnippetsBundle.ts @@ -0,0 +1,20 @@ +const glob = require('glob') +const fs = require('fs') + +glob('./snippets/snippets/**/*.ts', (_: any, files: readonly string[]) => { + const result = files + .map(file => { + const contents = fs.readFileSync(file, 'utf8') + return `export const ${file + .replace(/\.\/snippets\/snippets\/\w+\//, '') + .replace(/\.ts/, '')} = \`${contents.trim()}\`` + }) + .join('\n\n') + + fs.writeFile('./src/lib/snippets.ts', `${result}\n`, (err: any) => { + if (err) { + throw err + } + console.log('snippets generated') + }) +}) diff --git a/snippets/snippets/generics/cupt.ts b/snippets/snippets/generics/cupt.ts new file mode 100644 index 0000000..4474bc0 --- /dev/null +++ b/snippets/snippets/generics/cupt.ts @@ -0,0 +1,20 @@ +function simpleUseState() { + let state: number + const getState = () => state + const setState = (x: number) => { + state = x + } + return { + getState, + setState + } +} + +const { + getState, + setState +} = simpleUseState() +setState(1) +console.log(getState()) +setState(2) +console.log(getState()) diff --git a/snippets/snippets/generics/kiyi.ts b/snippets/snippets/generics/kiyi.ts new file mode 100644 index 0000000..572326f --- /dev/null +++ b/snippets/snippets/generics/kiyi.ts @@ -0,0 +1,5 @@ +// Confused by generics code like this? +function getProperty( + obj: T, + key: K +) diff --git a/snippets/tsconfig.json b/snippets/tsconfig.json new file mode 100644 index 0000000..74d83a2 --- /dev/null +++ b/snippets/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../tsconfig.snippets.json" +} diff --git a/src/components/CodeBlock.tsx b/src/components/CodeBlock.tsx index 8c65d1d..1d9f2d1 100644 --- a/src/components/CodeBlock.tsx +++ b/src/components/CodeBlock.tsx @@ -7,7 +7,7 @@ import PrismHighlight, { defaultProps } from 'prism-react-renderer' import theme from 'src/lib/prismTheme' const CodeBlock = ({ - children, + snippet, shouldHighlight, result, // pointToRunButton, @@ -15,7 +15,7 @@ const CodeBlock = ({ caption, noHighlight }: { - children: string + snippet: string shouldHighlight?: (lineNumber: number, tokenNumber: number) => boolean result?: string // pointToRunButton?: boolean @@ -45,7 +45,7 @@ const CodeBlock = ({ )} diff --git a/src/lib/snippets.ts b/src/lib/snippets.ts new file mode 100644 index 0000000..69c3676 --- /dev/null +++ b/src/lib/snippets.ts @@ -0,0 +1,26 @@ +export const cupt = `function simpleUseState() { + let state: number + const getState = () => state + const setState = (x: number) => { + state = x + } + return { + getState, + setState + } +} + +const { + getState, + setState +} = simpleUseState() +setState(1) +console.log(getState()) +setState(2) +console.log(getState())` + +export const kiyi = `// Confused by generics code like this? +function getProperty( + obj: T, + key: K +)` diff --git a/src/pages/generics.tsx b/src/pages/generics.tsx index e696219..3b9412b 100644 --- a/src/pages/generics.tsx +++ b/src/pages/generics.tsx @@ -4,6 +4,7 @@ import { P } from 'src/components/ContentTags' import EmojiSeparator from 'src/components/EmojiSeparator' import CodeBlock from 'src/components/CodeBlock' import underConstructionCard from 'src/lib/underConstructionCard' +import * as snippets from 'src/lib/snippets' const Page = () => ( ( title: 'TypeScript Generics Too Hard?', content: ( <> - {`// Confused by generics code like this? -function getProperty( - obj: T, - key: K -) { /* ... */ }`} +

If you’re (1) new to TypeScript, (2) new to{' '} generics, and (3) struggling to diff --git a/tsconfig.snippets.json b/tsconfig.snippets.json new file mode 100644 index 0000000..c6ddd24 --- /dev/null +++ b/tsconfig.snippets.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "target": "es2017", + "module": "commonjs", + "lib": ["es2017"], + "isolatedModules": false + }, + "include": ["./snippets"] +} diff --git a/yarn.lock b/yarn.lock index 3d61075..30e5d9d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1082,6 +1082,20 @@ resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== +"@types/events@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" + integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== + +"@types/glob@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" + integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== + dependencies: + "@types/events" "*" + "@types/minimatch" "*" + "@types/node" "*" + "@types/json-schema@^7.0.3": version "7.0.3" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" @@ -1092,6 +1106,16 @@ resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-1.15.2.tgz#528f11f7d6dc08cec0445d4bea8065a5bb6989b2" integrity sha512-zHPoyVrLvNaiMRYdhmh88Rn489ZgAgbc6iLxR5Yi0VCNfeNYHcszbhJV2vDHLNrVGy35BPtWBRn4OP2F9BBvFw== +"@types/minimatch@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== + +"@types/node@*": + version "12.12.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.8.tgz#dab418655af39ce2fa99286a0bed21ef8072ac9d" + integrity sha512-XLla8N+iyfjvsa0KKV+BP/iGSoTmwxsu5Ci5sM33z9TjohF72DEz95iNvD6pPmemvbQgxAv/909G73gUn8QR7w== + "@types/node@^12.12.7": version "12.12.7" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11" @@ -1447,6 +1471,11 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" +arg@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.1.tgz#485f8e7c390ce4c5f78257dbea80d4be11feda4c" + integrity sha512-SlmP3fEA88MBv0PypnXZ8ZfJhwmDeIE3SP71j37AiXQBXYosPV0x6uISAaHYSlSVhmHOVkomen0tbGk6Anlebw== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -2574,6 +2603,11 @@ devalue@2.0.0: resolved "https://registry.yarnpkg.com/devalue/-/devalue-2.0.0.tgz#2afa0b7c1bb35bebbef792498150663fdcd33c68" integrity sha512-6H2FBD5DPnQS75UWJtQjoVeKZlmXoa765UgYS5RQnx6Ay9LUhUld0w1/D6cYdrY+wnu6XQNlpEBfnJUZK0YyPQ== +diff@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" + integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -3279,7 +3313,7 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^7.0.3, glob@^7.1.3, glob@^7.1.4: +glob@^7.0.3, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -4084,6 +4118,11 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" +make-error@^1.1.1: + version "1.3.5" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" + integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== + mamacro@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" @@ -6061,7 +6100,7 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@~0.5.10, source-map-support@~0.5.12: +source-map-support@^0.5.6, source-map-support@~0.5.10, source-map-support@~0.5.12: version "0.5.16" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== @@ -6513,6 +6552,17 @@ traverse@0.6.6: resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= +ts-node@^8.5.2: + version "8.5.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.5.2.tgz#434f6c893bafe501a30b32ac94ee36809ba2adce" + integrity sha512-W1DK/a6BGoV/D4x/SXXm6TSQx6q3blECUzd5TN+j56YEMX3yPVMpHsICLedUw3DvGF3aTQ8hfdR9AKMaHjIi+A== + dependencies: + arg "^4.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.6" + yn "^3.0.0" + ts-pnp@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.4.tgz#ae27126960ebaefb874c6d7fa4729729ab200d90" @@ -6900,3 +6950,8 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yn@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From 58f1da833df4563492f7aa66fa756c06f49a014e Mon Sep 17 00:00:00 2001 From: Shu Uesugi Date: Mon, 18 Nov 2019 19:20:38 -0800 Subject: [PATCH 2/3] createState example --- package.json | 1 + snippets/bin/generateSnippetsBundle.ts | 36 ++++++---- snippets/snippets/generics/cbeq.ts | 7 ++ snippets/snippets/generics/cupt.ts | 20 +++--- src/components/CodeBlock.tsx | 15 +++-- src/components/ContentTags/Code.tsx | 21 ++++++ src/components/ContentTags/Highlight.tsx | 19 ++++++ src/components/ContentTags/index.tsx | 2 + src/lib/snippets.ts | 30 +++++---- src/lib/theme/colors.ts | 4 +- src/lib/theme/fontSizes.ts | 3 +- src/lib/theme/maxWidths.ts | 2 +- src/pages/generics.tsx | 28 +++++++- yarn.lock | 84 +++++++++++++++++++++++- 14 files changed, 217 insertions(+), 55 deletions(-) create mode 100644 snippets/snippets/generics/cbeq.ts create mode 100644 src/components/ContentTags/Code.tsx create mode 100644 src/components/ContentTags/Highlight.tsx diff --git a/package.json b/package.json index 694a4ae..9278b33 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@typescript-eslint/parser": "^2.7.0", "babel-eslint": "^10.0.3", "babel-plugin-emotion": "^10.0.23", + "chokidar": "^3.3.0", "eslint": "^6.5.1", "eslint-config-prettier": "^6.4.0", "eslint-plugin-import": "^2.18.2", diff --git a/snippets/bin/generateSnippetsBundle.ts b/snippets/bin/generateSnippetsBundle.ts index 598c305..3caeae1 100644 --- a/snippets/bin/generateSnippetsBundle.ts +++ b/snippets/bin/generateSnippetsBundle.ts @@ -1,20 +1,28 @@ const glob = require('glob') const fs = require('fs') +const chokidar = require('chokidar') -glob('./snippets/snippets/**/*.ts', (_: any, files: readonly string[]) => { - const result = files - .map(file => { - const contents = fs.readFileSync(file, 'utf8') - return `export const ${file - .replace(/\.\/snippets\/snippets\/\w+\//, '') - .replace(/\.ts/, '')} = \`${contents.trim()}\`` - }) - .join('\n\n') +const regenerate = () => { + glob('./snippets/snippets/**/*.ts', (_: any, files: readonly string[]) => { + const result = files + .map(file => { + const contents = fs.readFileSync(file, 'utf8') + return `export const ${file + .replace(/\.\/snippets\/snippets\/\w+\//, '') + .replace(/\.ts/, '')} = \`${contents.trim()}\`` + }) + .join('\n\n') - fs.writeFile('./src/lib/snippets.ts', `${result}\n`, (err: any) => { - if (err) { - throw err - } - console.log('snippets generated') + fs.writeFile('./src/lib/snippets.ts', `${result}\n`, (err: any) => { + if (err) { + throw err + } + console.log('snippets generated') + }) }) +} + +regenerate() +chokidar.watch('./snippets/snippets/**/*.ts').on('change', () => { + regenerate() }) diff --git a/snippets/snippets/generics/cbeq.ts b/snippets/snippets/generics/cbeq.ts new file mode 100644 index 0000000..9e8f346 --- /dev/null +++ b/snippets/snippets/generics/cbeq.ts @@ -0,0 +1,7 @@ +const { getState, setState } = createState() + +setState(1) +console.log(getState()) + +setState(2) +console.log(getState()) diff --git a/snippets/snippets/generics/cupt.ts b/snippets/snippets/generics/cupt.ts index 4474bc0..6773316 100644 --- a/snippets/snippets/generics/cupt.ts +++ b/snippets/snippets/generics/cupt.ts @@ -1,20 +1,16 @@ -function simpleUseState() { +function createState() { let state: number - const getState = () => state - const setState = (x: number) => { + + function getState() { + return state + } + + function setState(x: number) { state = x } + return { getState, setState } } - -const { - getState, - setState -} = simpleUseState() -setState(1) -console.log(getState()) -setState(2) -console.log(getState()) diff --git a/src/components/CodeBlock.tsx b/src/components/CodeBlock.tsx index 1d9f2d1..c51799d 100644 --- a/src/components/CodeBlock.tsx +++ b/src/components/CodeBlock.tsx @@ -47,18 +47,19 @@ const CodeBlock = ({ {...defaultProps} code={snippet} theme={theme} - language={noHighlight ? 'diff' : 'javascript'} + language={noHighlight ? 'diff' : 'typescript'} > {({ tokens, getLineProps, getTokenProps }) => (

 {
+  const { colors } = useTheme()
+  return (
+    
+  )
+}
+
+export default Code
diff --git a/src/components/ContentTags/Highlight.tsx b/src/components/ContentTags/Highlight.tsx
new file mode 100644
index 0000000..e81daef
--- /dev/null
+++ b/src/components/ContentTags/Highlight.tsx
@@ -0,0 +1,19 @@
+/** @jsx jsx */
+import { css, jsx } from '@emotion/core'
+import useTheme from 'src/hooks/useTheme'
+
+const Highlight = (props: JSX.IntrinsicElements['span']) => {
+  const { colors } = useTheme()
+  return (
+    
+  )
+}
+
+export default Highlight
diff --git a/src/components/ContentTags/index.tsx b/src/components/ContentTags/index.tsx
index 5352edc..67d4055 100644
--- a/src/components/ContentTags/index.tsx
+++ b/src/components/ContentTags/index.tsx
@@ -1,2 +1,4 @@
 export { default as P } from 'src/components/ContentTags/P'
 export { default as H3 } from 'src/components/ContentTags/H3'
+export { default as Code } from 'src/components/ContentTags/Code'
+export { default as Highlight } from 'src/components/ContentTags/Highlight'
diff --git a/src/lib/snippets.ts b/src/lib/snippets.ts
index 69c3676..c24e743 100644
--- a/src/lib/snippets.ts
+++ b/src/lib/snippets.ts
@@ -1,23 +1,27 @@
-export const cupt = `function simpleUseState() {
+export const cbeq = `const { getState, setState } = createState()
+
+setState(1)
+console.log(getState())
+
+setState(2)
+console.log(getState())`
+
+export const cupt = `function createState() {
   let state: number
-  const getState = () => state
-  const setState = (x: number) => {
+
+  function getState() {
+    return state
+  }
+
+  function setState(x: number) {
     state = x
   }
+
   return {
     getState,
     setState
   }
-}
-
-const {
-  getState,
-  setState
-} = simpleUseState()
-setState(1)
-console.log(getState())
-setState(2)
-console.log(getState())`
+}`
 
 export const kiyi = `// Confused by generics code like this?
 function getProperty(
diff --git a/src/lib/theme/colors.ts b/src/lib/theme/colors.ts
index 90e0a85..da0c17d 100644
--- a/src/lib/theme/colors.ts
+++ b/src/lib/theme/colors.ts
@@ -2,8 +2,8 @@ export const allColors = {
   black: '#260808',
   lightYellow1: '#FEF5DD',
   lightYellow2: '#FFE8BF',
-  lightPink1: '#FFF2E4',
-  lightPink2: '#FFDFC7',
+  lightPink: '#FFF2E4',
+  lightGreen: '#DFE9CE',
   brown: '#806538',
   pink: '#FCCFC0',
   white: '#FFFFFF',
diff --git a/src/lib/theme/fontSizes.ts b/src/lib/theme/fontSizes.ts
index 11dbf9e..cb9c82a 100644
--- a/src/lib/theme/fontSizes.ts
+++ b/src/lib/theme/fontSizes.ts
@@ -13,6 +13,7 @@ export const allFontSizes = {
   5: 5
 }
 
-const fontSizes = (x: keyof typeof allFontSizes) => `${allFontSizes[x]}rem`
+const fontSizes = (x: keyof typeof allFontSizes, useEm?: boolean) =>
+  `${allFontSizes[x]}${useEm ? 'em' : 'rem'}`
 
 export default fontSizes
diff --git a/src/lib/theme/maxWidths.ts b/src/lib/theme/maxWidths.ts
index 1a352c0..9f57886 100644
--- a/src/lib/theme/maxWidths.ts
+++ b/src/lib/theme/maxWidths.ts
@@ -1,5 +1,5 @@
 export const allMaxWidths = {
-  sm: (1140 / 12) * 6,
+  sm: (1140 / 12) * 5,
   md: (1140 / 12) * 8,
   lg: 1140
 }
diff --git a/src/pages/generics.tsx b/src/pages/generics.tsx
index 3b9412b..9cc5b1d 100644
--- a/src/pages/generics.tsx
+++ b/src/pages/generics.tsx
@@ -1,6 +1,6 @@
 import React from 'react'
 import PostPage from 'src/components/PostPage'
-import { P } from 'src/components/ContentTags'
+import { P, Code, Highlight } from 'src/components/ContentTags'
 import EmojiSeparator from 'src/components/EmojiSeparator'
 import CodeBlock from 'src/components/CodeBlock'
 import underConstructionCard from 'src/lib/underConstructionCard'
@@ -11,7 +11,7 @@ const Page = () => (
     articleKey="generics"
     cards={[
       {
-        title: 'TypeScript Generics Too Hard?',
+        title: <>TypeScript Generics Too Hard?,
         content: (
           <>
             
@@ -52,6 +52,30 @@ const Page = () => (
           
         )
       },
+      {
+        title: (
+          <>
+            Let’s talk about createState()
+          
+        ),
+        content: (
+          <>
+            

+ We’ll use the following createState() function to + learn about generics. Take a look below: +

+ +

+ Let’s check your understanding.{' '} + + What gets printed out to the console when you run the following + code? + +

+ + + ) + }, underConstructionCard ]} /> diff --git a/yarn.lock b/yarn.lock index 30e5d9d..240b47b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1458,6 +1458,14 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -1743,6 +1751,11 @@ binary-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== +binary-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" + integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== + bluebird@^3.5.0, bluebird@^3.5.5: version "3.7.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de" @@ -1782,6 +1795,13 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -2003,6 +2023,21 @@ chokidar@^2.0.2, chokidar@^2.0.4: optionalDependencies: fsevents "^1.2.7" +chokidar@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" + integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.2.0" + optionalDependencies: + fsevents "~2.1.1" + chownr@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" @@ -3107,6 +3142,13 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + find-cache-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" @@ -3259,6 +3301,11 @@ fsevents@^1.2.7: nan "^2.12.1" node-pre-gyp "^0.12.0" +fsevents@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" + integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -3301,7 +3348,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0: +glob-parent@^5.0.0, glob-parent@~5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== @@ -3644,6 +3691,13 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-buffer@^1.0.2, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -3742,7 +3796,7 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0, is-glob@^4.0.1: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== @@ -3756,6 +3810,11 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + is-obj@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" @@ -4587,7 +4646,7 @@ normalize-path@^2.1.1: dependencies: remove-trailing-separator "^1.0.1" -normalize-path@^3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -5000,6 +5059,11 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +picomatch@^2.0.4: + version "2.1.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5" + integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA== + pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -5696,6 +5760,13 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" +readdirp@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" + integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== + dependencies: + picomatch "^2.0.4" + recursive-readdir@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" @@ -6532,6 +6603,13 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" From 79aa4d3a3ffc267f0f63d5eb903168f7c2746a96 Mon Sep 17 00:00:00 2001 From: Shu Uesugi Date: Mon, 18 Nov 2019 20:39:25 -0800 Subject: [PATCH 3/3] Slide 2 --- package.json | 3 +- snippets/snippets/generics/udpv.ts | 24 +++ .../ButtonWithTouchActiveStates.tsx | 43 ++++++ src/components/Card.tsx | 23 ++- src/components/CodeBlock.tsx | 146 ++++++++---------- src/components/ContentTags/Code.tsx | 2 +- src/components/GlobalStyles.tsx | 8 +- src/components/RunButtonText.tsx | 15 ++ src/lib/snippets.ts | 25 +++ src/lib/theme/colors.ts | 6 +- src/lib/underConstructionCard.tsx | 2 +- src/pages/generics.tsx | 44 +++++- 12 files changed, 233 insertions(+), 108 deletions(-) create mode 100644 snippets/snippets/generics/udpv.ts create mode 100644 src/components/ButtonWithTouchActiveStates.tsx create mode 100644 src/components/RunButtonText.tsx diff --git a/package.json b/package.json index 9278b33..295fe46 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,8 @@ "eslint": "eslint --ext .js,.ts,.tsx .", "eslint:fix": "eslint --ext .js,.ts,.tsx --fix .", "svgr": "svgr --ext tsx --no-svgo --no-dimensions -d .", - "snippets": "ts-node --project tsconfig.snippets.json snippets/bin/generateSnippetsBundle.ts" + "snippets": "runSnippet snippets/bin/generateSnippetsBundle.ts", + "runSnippet": "ts-node --project tsconfig.snippets.json" }, "devDependencies": { "@svgr/cli": "^4.3.3", diff --git a/snippets/snippets/generics/udpv.ts b/snippets/snippets/generics/udpv.ts new file mode 100644 index 0000000..e5e5dc7 --- /dev/null +++ b/snippets/snippets/generics/udpv.ts @@ -0,0 +1,24 @@ +function createState() { + let state: number + + function getState() { + return state + } + + function setState(x: number) { + state = x + } + + return { + getState, + setState + } +} + +const { getState, setState } = createState() + +setState(1) +console.log(getState()) + +setState(2) +console.log(getState()) diff --git a/src/components/ButtonWithTouchActiveStates.tsx b/src/components/ButtonWithTouchActiveStates.tsx new file mode 100644 index 0000000..851841c --- /dev/null +++ b/src/components/ButtonWithTouchActiveStates.tsx @@ -0,0 +1,43 @@ +/** @jsx jsx */ +import { css, jsx } from '@emotion/core' +import { useState } from 'react' + +type ButtonWithTouchActiveStatesProps< + T = JSX.IntrinsicElements['button'] +> = T & { + activeBackgroundColor: string +} + +const ButtonWithTouchActiveStates = ({ + activeBackgroundColor, + ...props +}: ButtonWithTouchActiveStatesProps) => { + const [isActive, setIsActive] = useState(false) + const activate = () => { + if (!props.disabled) { + // NOTE: Originally tried to call the callback here and do e.preventDefault() + // to prevent mouse click event from happening, so that callback fires + // on tap start instead of on tap end, but that was buggy so ended up removing. + setIsActive(true) + } + } + const deactivate = () => { + setIsActive(false) + } + return ( +
)}
- {/* result && ( + {result && ( <>
{resultVisible ? (
- - Result:{' '} - - - {result} - + {result}
) : ( - <> +
{pointToRunButton && ( - +
+ - ← Press this button! - + ` + ]} + > + ↑ Press this button! +
+ )} - +
)}
- )*/} + )} ) } diff --git a/src/components/ContentTags/Code.tsx b/src/components/ContentTags/Code.tsx index 4a5bb85..f50a1c7 100644 --- a/src/components/ContentTags/Code.tsx +++ b/src/components/ContentTags/Code.tsx @@ -10,8 +10,8 @@ const Code = (props: JSX.IntrinsicElements['code']) => { css={[ css` font-size: 0.9em; - color: ${colors('red')}; word-break: break-word; + background: ${colors('lightPink2')}; ` ]} /> diff --git a/src/components/GlobalStyles.tsx b/src/components/GlobalStyles.tsx index 7477490..047f7b4 100644 --- a/src/components/GlobalStyles.tsx +++ b/src/components/GlobalStyles.tsx @@ -71,11 +71,11 @@ const GlobalStyles = ({ children }: { children: React.ReactNode }) => { @font-face { font-family: 'Iosevka Web'; font-weight: 700; - font-style: oblique; + font-style: normal; font-display: fallback; - src: url('/fonts/iosevka-boldoblique.woff2') format('woff2'), - url('/fonts/iosevka-boldoblique.woff') format('woff'), - url('/fonts/iosevka-boldoblique.ttf') format('truetype'); + src: url('/fonts/iosevka-bold.woff2') format('woff2'), + url('/fonts/iosevka-bold.woff') format('woff'), + url('/fonts/iosevka-bold.ttf') format('truetype'); } code, diff --git a/src/components/RunButtonText.tsx b/src/components/RunButtonText.tsx new file mode 100644 index 0000000..a1544d8 --- /dev/null +++ b/src/components/RunButtonText.tsx @@ -0,0 +1,15 @@ +/** @jsx jsx */ +import { css, jsx } from '@emotion/core' +import Emoji from 'src/components/Emoji' + +const RunButtonText = () => ( + + Run + +) + +export default RunButtonText diff --git a/src/lib/snippets.ts b/src/lib/snippets.ts index c24e743..1e19e1a 100644 --- a/src/lib/snippets.ts +++ b/src/lib/snippets.ts @@ -28,3 +28,28 @@ function getProperty( obj: T, key: K )` + +export const udpv = `function createState() { + let state: number + + function getState() { + return state + } + + function setState(x: number) { + state = x + } + + return { + getState, + setState + } +} + +const { getState, setState } = createState() + +setState(1) +console.log(getState()) + +setState(2) +console.log(getState())` diff --git a/src/lib/theme/colors.ts b/src/lib/theme/colors.ts index da0c17d..0e03b75 100644 --- a/src/lib/theme/colors.ts +++ b/src/lib/theme/colors.ts @@ -2,10 +2,12 @@ export const allColors = { black: '#260808', lightYellow1: '#FEF5DD', lightYellow2: '#FFE8BF', - lightPink: '#FFF2E4', + lightPink1: '#FFF2E4', + lightPink2: '#FFE7DD', lightGreen: '#DFE9CE', brown: '#806538', - pink: '#FCCFC0', + lightBrown: '#E9D1AC', + pink: '#FFD9CC', white: '#FFFFFF', white75: 'rgba(255, 255, 255, 0.75)', paleGreen: '#C8DCC7', diff --git a/src/lib/underConstructionCard.tsx b/src/lib/underConstructionCard.tsx index f38e6fb..8ecd25f 100644 --- a/src/lib/underConstructionCard.tsx +++ b/src/lib/underConstructionCard.tsx @@ -5,7 +5,7 @@ const underConstructionCard = { title: 'Under Construction', content: ( <> -

This article is currently under construction.

+

This article is still in draft. Check back again soon!

) } diff --git a/src/pages/generics.tsx b/src/pages/generics.tsx index 9cc5b1d..f630405 100644 --- a/src/pages/generics.tsx +++ b/src/pages/generics.tsx @@ -5,6 +5,7 @@ import EmojiSeparator from 'src/components/EmojiSeparator' import CodeBlock from 'src/components/CodeBlock' import underConstructionCard from 'src/lib/underConstructionCard' import * as snippets from 'src/lib/snippets' +import RunButtonText from 'src/components/RunButtonText' const Page = () => ( ( content: ( <>

- We’ll use the following createState() function to - learn about generics. Take a look below: + First, I created a function called createState(){' '} + below. We’ll use this function to talk about generics.

- Let’s check your understanding.{' '} + When you run createState(), it returns two functions:{' '} + getState() and setState(). You can use + these functions to set and get the variable called{' '} + state. +

+

+ Let’s try it out!{' '} What gets printed out to the console when you run the following code? + {' '} + Try to guess first, and then{' '} + + press the button + . +

+ + 1
2 + + } + /> +

+ It printed 1, then 2. Pretty simple, + right?

- - ) + ), + footer: { + content: ( + <> +

+ Note: If you’ve used React, you might realize + that it’s kind of like the useState() hook. +

+ + ) + } }, underConstructionCard ]}