From 2fda910acd5bc5ed84ef2e3697d811bd93da8a54 Mon Sep 17 00:00:00 2001
From: Shu Uesugi
Date: Wed, 20 Nov 2019 20:37:40 -0800
Subject: [PATCH 1/3] Set default type
---
snippets/snippets/generics/gzwe.ts | 5 +++
snippets/snippets/generics/nuzz.ts | 26 ++++++++++++
snippets/snippets/generics/thxf.ts | 4 ++
snippets/snippets/generics/xfwf.ts | 6 +++
src/components/ContentTags/Highlight.tsx | 8 +++-
src/lib/snippets.ts | 45 ++++++++++++++++++++
src/pages/generics.tsx | 53 ++++++++++++++++++++++--
7 files changed, 141 insertions(+), 6 deletions(-)
create mode 100644 snippets/snippets/generics/gzwe.ts
create mode 100644 snippets/snippets/generics/nuzz.ts
create mode 100644 snippets/snippets/generics/thxf.ts
create mode 100644 snippets/snippets/generics/xfwf.ts
diff --git a/snippets/snippets/generics/gzwe.ts b/snippets/snippets/generics/gzwe.ts
new file mode 100644
index 0000000..b8e4e5a
--- /dev/null
+++ b/snippets/snippets/generics/gzwe.ts
@@ -0,0 +1,5 @@
+// Don’t need to use
+const numState = makeState()
+
+numState.setState(1)
+console.log(numState.getState())
diff --git a/snippets/snippets/generics/nuzz.ts b/snippets/snippets/generics/nuzz.ts
new file mode 100644
index 0000000..d55b6a7
--- /dev/null
+++ b/snippets/snippets/generics/nuzz.ts
@@ -0,0 +1,26 @@
+interface State {
+ value?: V
+ author?: A
+}
+
+function makeState<
+ V extends number | string,
+ A extends string
+>() {
+ let state: State = {}
+
+ function getState() {
+ return state
+ }
+
+ function setState(value: V, author: A) {
+ state.value = value
+ state.author = author
+ }
+
+ return { getState, setState }
+}
+
+const state = makeState()
+state.setState(1, 'cat')
+console.log(state.getState())
diff --git a/snippets/snippets/generics/thxf.ts b/snippets/snippets/generics/thxf.ts
new file mode 100644
index 0000000..24deecd
--- /dev/null
+++ b/snippets/snippets/generics/thxf.ts
@@ -0,0 +1,4 @@
+// Set default type of S as number
+function makeState<
+ S extends number | string = number
+>()
diff --git a/snippets/snippets/generics/xfwf.ts b/snippets/snippets/generics/xfwf.ts
new file mode 100644
index 0000000..538824b
--- /dev/null
+++ b/snippets/snippets/generics/xfwf.ts
@@ -0,0 +1,6 @@
+// Can we make it so that, is the
+// default type paramter of makeState()?
+
+// We want these two statements to be equivalent
+const numState1 = makeState()
+const numState2 = makeState()
diff --git a/src/components/ContentTags/Highlight.tsx b/src/components/ContentTags/Highlight.tsx
index e81daef..0dfd599 100644
--- a/src/components/ContentTags/Highlight.tsx
+++ b/src/components/ContentTags/Highlight.tsx
@@ -1,15 +1,19 @@
/** @jsx jsx */
import { css, jsx } from '@emotion/core'
import useTheme from 'src/hooks/useTheme'
+import { allColors } from 'src/lib/theme/colors'
-const Highlight = (props: JSX.IntrinsicElements['span']) => {
+const Highlight = ({
+ color,
+ ...props
+}: JSX.IntrinsicElements['span'] & { color?: keyof typeof allColors }) => {
const { colors } = useTheme()
return (
diff --git a/src/lib/snippets.ts b/src/lib/snippets.ts
index 5e10266..e03c158 100644
--- a/src/lib/snippets.ts
+++ b/src/lib/snippets.ts
@@ -111,6 +111,12 @@ export const gkgi = `function makeState() {
return { getState, setState }
}`
+export const gzwe = `// Don’t need to use
+const numState = makeState()
+
+numState.setState(1)
+console.log(numState.getState())`
+
export const hkgv = `// Creates a string-only state
const strState = makeState()
strState.setState('foo')
@@ -149,6 +155,33 @@ export const nnyl = `function makeState() {
return { getState, setState }
}`
+export const nuzz = `interface State {
+ value?: V
+ author?: A
+}
+
+function makeState<
+ V extends number | string,
+ A extends string
+>() {
+ let state: State = {}
+
+ function getState() {
+ return state
+ }
+
+ function setState(value: V, author: A) {
+ state.value = value
+ state.author = author
+ }
+
+ return { getState, setState }
+}
+
+const state = makeState()
+state.setState(1, 'cat')
+console.log(state.getState())`
+
export const osaa = `function makeState() {
// Change to string
let state: string
@@ -197,6 +230,11 @@ export const stkh = `const { getState, setState } = makeState()
setState('foo')
console.log(getState())`
+export const thxf = `// Set default type of S as number
+function makeState<
+ S extends number | string = number
+>()`
+
export const udpv = `function makeState() {
let state: number
@@ -224,6 +262,13 @@ export const xeax = `const { getState, setState } = makeState()
setState('foo')
console.log(getState())`
+export const xfwf = `// Can we make it so that, is the
+// default type paramter of makeState()?
+
+// We want these two statements to be equivalent
+const numState1 = makeState()
+const numState2 = makeState()`
+
export const ystu = `function makeState() {
let state: number | string
diff --git a/src/pages/generics.tsx b/src/pages/generics.tsx
index 4589bc3..8236794 100644
--- a/src/pages/generics.tsx
+++ b/src/pages/generics.tsx
@@ -51,8 +51,14 @@ const Page = () => (
content: (
<>
- Note: If you didn’t find generics to be
- difficult, this tutorial might be too easy for you.
+ Note: If you already understand generics, you
+ won’t find anything new in this tutorial. However,{' '}
+
+ you might know someone (maybe your colleague or your Twitter
+ follower) who’s struggling with generics
+
+ . If so, I’d appreciate it if you could share this article with
+ them.
>
)
@@ -406,12 +412,51 @@ const Page = () => (
/>
It resulted in an error, which is what we want!
- As you just saw, you can specify what’s allowed
- for the type argument(s) of a generic function.
+ As you just saw, you can specify what’s allowed for the type
+ argument(s) of a generic function.
+ It can be annoying to specify type arguments like{' '}
+ <number> or <string> every
+ time you call makeState().
+
+
+ So here’s an idea:{' '}
+
+ Can we make it so that <number> is the
+ default type argument of makeState()?
+ {' '}
+ We want to make it so that, if the type argument is missing, it’s
+ set as number by default.
+
+
+
+ To make this happen, we can specify the default type of{' '}
+ S by adding = number at the end. It’s
+ kind of like setting default values for regular function
+ parameters, right?
+
+ By doing this, you can create a number-only state without
+ specifying the type:
+
+
+ >
+ )
+ },
underConstructionCard
]}
/>
From fd6cf376b9bfebd8690a2ecd68d36ae6467ff8f0 Mon Sep 17 00:00:00 2001
From: Shu Uesugi
Date: Thu, 21 Nov 2019 11:18:19 -0800
Subject: [PATCH 2/3] Up to step 9
---
snippets/snippets/generics/bqvz.ts | 7 ++
snippets/snippets/generics/kbld.ts | 7 ++
snippets/snippets/generics/nuzz.ts | 18 ++---
snippets/snippets/generics/nyih.ts | 5 ++
snippets/snippets/generics/pjcw.ts | 5 ++
snippets/snippets/generics/qini.ts | 7 ++
snippets/snippets/generics/wpru.ts | 7 ++
src/components/Card.tsx | 19 ++---
src/components/ContentTags/Highlight.tsx | 2 +-
src/components/ContentTags/Hr.tsx | 22 ++++++
src/components/ContentTags/index.tsx | 1 +
src/components/Emoji/Twitter.tsx | 15 ++++
src/components/Emoji/index.tsx | 4 +-
src/components/PostPage.tsx | 4 +-
src/components/TwitterLink.tsx | 23 ++++++
src/lib/snippets.ts | 64 ++++++++++++----
src/lib/theme/colors.ts | 4 +-
src/pages/generics.tsx | 97 ++++++++++++++++++++----
18 files changed, 255 insertions(+), 56 deletions(-)
create mode 100644 snippets/snippets/generics/bqvz.ts
create mode 100644 snippets/snippets/generics/kbld.ts
create mode 100644 snippets/snippets/generics/nyih.ts
create mode 100644 snippets/snippets/generics/pjcw.ts
create mode 100644 snippets/snippets/generics/qini.ts
create mode 100644 snippets/snippets/generics/wpru.ts
create mode 100644 src/components/ContentTags/Hr.tsx
create mode 100644 src/components/Emoji/Twitter.tsx
create mode 100644 src/components/TwitterLink.tsx
diff --git a/snippets/snippets/generics/bqvz.ts b/snippets/snippets/generics/bqvz.ts
new file mode 100644
index 0000000..f08611b
--- /dev/null
+++ b/snippets/snippets/generics/bqvz.ts
@@ -0,0 +1,7 @@
+// Declare a generic function
+function genericFunc() {
+ // You can use T here
+}
+
+// Call it: T will be number
+genericFunc()
diff --git a/snippets/snippets/generics/kbld.ts b/snippets/snippets/generics/kbld.ts
new file mode 100644
index 0000000..5cce849
--- /dev/null
+++ b/snippets/snippets/generics/kbld.ts
@@ -0,0 +1,7 @@
+// Limits the type of T
+function genericFunc()
+
+// Success
+genericFunc()
+// Error
+genericFunc()
diff --git a/snippets/snippets/generics/nuzz.ts b/snippets/snippets/generics/nuzz.ts
index d55b6a7..d451c03 100644
--- a/snippets/snippets/generics/nuzz.ts
+++ b/snippets/snippets/generics/nuzz.ts
@@ -1,26 +1,20 @@
-interface State {
- value?: V
- author?: A
-}
-
function makeState<
- V extends number | string,
- A extends string
+ A extends number | string,
+ B extends number | string
>() {
- let state: State = {}
+ let state: [A, B]
function getState() {
return state
}
- function setState(value: V, author: A) {
- state.value = value
- state.author = author
+ function setState(first: A, second: B) {
+ state = [first, second]
}
return { getState, setState }
}
-const state = makeState()
+const state = makeState()
state.setState(1, 'cat')
console.log(state.getState())
diff --git a/snippets/snippets/generics/nyih.ts b/snippets/snippets/generics/nyih.ts
new file mode 100644
index 0000000..ef33b45
--- /dev/null
+++ b/snippets/snippets/generics/nyih.ts
@@ -0,0 +1,5 @@
+// Set the default type of T
+function genericFunc()
+
+// T will be number inside the function
+genericFunc()
diff --git a/snippets/snippets/generics/pjcw.ts b/snippets/snippets/generics/pjcw.ts
new file mode 100644
index 0000000..7651775
--- /dev/null
+++ b/snippets/snippets/generics/pjcw.ts
@@ -0,0 +1,5 @@
+// Set default value of x
+function regularFunc(x = 2)
+
+// x will be 2 inside the function
+regularFunc()
diff --git a/snippets/snippets/generics/qini.ts b/snippets/snippets/generics/qini.ts
new file mode 100644
index 0000000..3729689
--- /dev/null
+++ b/snippets/snippets/generics/qini.ts
@@ -0,0 +1,7 @@
+// Specify x to be number
+function regularFunc(x: number)
+
+// Success
+regularFunc(1)
+// Error
+regularFunc('foo')
diff --git a/snippets/snippets/generics/wpru.ts b/snippets/snippets/generics/wpru.ts
new file mode 100644
index 0000000..567794e
--- /dev/null
+++ b/snippets/snippets/generics/wpru.ts
@@ -0,0 +1,7 @@
+// Declare a regular function
+function regularFunc(x: any) {
+ // You can use x here
+}
+
+// Call it: x will be 1
+regularFunc(1)
diff --git a/src/components/Card.tsx b/src/components/Card.tsx
index 121101d..20531ae 100644
--- a/src/components/Card.tsx
+++ b/src/components/Card.tsx
@@ -7,7 +7,7 @@ import { H3 } from 'src/components/ContentTags'
export interface CardProps {
children: React.ReactNode
- color?: 'default' | 'pink'
+ color?: 'default' | 'pink' | 'green'
slideNumber?: number
slideCount?: number
isLast?: boolean
@@ -27,15 +27,8 @@ export const backgroundColor = (
): keyof typeof allColors =>
({
default: 'lightYellow1' as const,
- pink: 'lightPink2' as const
- }[color])
-
-const slideLabelBgColor = (
- color: NonNullable
-): keyof typeof allColors =>
- ({
- default: 'brown' as const,
- pink: 'brown' as const
+ pink: 'lightPink2' as const,
+ green: 'lightGreen' as const
}[color])
const Card = ({
@@ -71,7 +64,7 @@ const Card = ({
font-size: ${fontSizes(0.75)};
line-height: 1;
color: ${colors('white')};
- background: ${colors(slideLabelBgColor(color))};
+ background: ${colors('brown')};
padding: ${spaces(0.25)} ${spaces(0.5)};
border-radius: 9999px;
user-select: none;
@@ -80,7 +73,7 @@ const Card = ({
<>
Slide{' '}
@@ -94,7 +87,7 @@ const Card = ({
{' '}
diff --git a/src/components/ContentTags/Highlight.tsx b/src/components/ContentTags/Highlight.tsx
index 0dfd599..4e2e9df 100644
--- a/src/components/ContentTags/Highlight.tsx
+++ b/src/components/ContentTags/Highlight.tsx
@@ -13,7 +13,7 @@ const Highlight = ({
{...props}
css={[
css`
- background: ${color ? colors(color) : colors('white')};
+ background: ${color ? colors(color) : colors('white85')};
`
]}
/>
diff --git a/src/components/ContentTags/Hr.tsx b/src/components/ContentTags/Hr.tsx
new file mode 100644
index 0000000..d317c8f
--- /dev/null
+++ b/src/components/ContentTags/Hr.tsx
@@ -0,0 +1,22 @@
+/** @jsx jsx */
+import { css, jsx } from '@emotion/core'
+import useTheme from 'src/hooks/useTheme'
+
+const Hr = (props: JSX.IntrinsicElements['hr']) => {
+ const { colors, spaces } = useTheme()
+ return (
+
+ )
+}
+
+export default Hr
diff --git a/src/components/ContentTags/index.tsx b/src/components/ContentTags/index.tsx
index 8e6b656..1aa7480 100644
--- a/src/components/ContentTags/index.tsx
+++ b/src/components/ContentTags/index.tsx
@@ -2,4 +2,5 @@ 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'
+export { default as Hr } from 'src/components/ContentTags/Hr'
export { Ul, Ol, UlLi, OlLi } from 'src/components/ContentTags/List'
diff --git a/src/components/Emoji/Twitter.tsx b/src/components/Emoji/Twitter.tsx
new file mode 100644
index 0000000..ff93634
--- /dev/null
+++ b/src/components/Emoji/Twitter.tsx
@@ -0,0 +1,15 @@
+import * as React from 'react'
+
+const Twitter = (props: React.SVGProps) => (
+
+)
+
+export default Twitter
diff --git a/src/components/Emoji/index.tsx b/src/components/Emoji/index.tsx
index 6c09a58..cba72f7 100644
--- a/src/components/Emoji/index.tsx
+++ b/src/components/Emoji/index.tsx
@@ -5,13 +5,15 @@ import CryingCat from 'src/components/Emoji/CryingCat'
import Question from 'src/components/Emoji/Question'
import Run from 'src/components/Emoji/Run'
import ChickEgg from 'src/components/Emoji/ChickEgg'
+import Twitter from 'src/components/Emoji/Twitter'
export const emojiToComponent = {
bird: Bird,
cryingCat: CryingCat,
question: Question,
run: Run,
- chickEgg: ChickEgg
+ chickEgg: ChickEgg,
+ twitter: Twitter
}
const Emoji = ({
diff --git a/src/components/PostPage.tsx b/src/components/PostPage.tsx
index f057b2b..a146502 100644
--- a/src/components/PostPage.tsx
+++ b/src/components/PostPage.tsx
@@ -14,6 +14,7 @@ export interface EpisodeCardType {
title?: React.ReactNode
content?: React.ReactNode
footer?: CardProps['footer']
+ color?: CardProps['color']
}
const PostPage = ({
@@ -96,8 +97,9 @@ const PostPage = ({
}
]}
>
- {cards.map(({ title, content, footer }, index) => (
+ {cards.map(({ title, content, footer, color }, index) => (
{
+ const tweetUrl = `https://twitter.com/intent/tweet?url=${encodeURIComponent(
+ url
+ )}&via=chibicode&text=${encodeURIComponent(title)}`
+ return (
+
+ {children}
+
+ )
+}
+
+export default TwitterLink
diff --git a/src/lib/snippets.ts b/src/lib/snippets.ts
index e03c158..3eb9dc6 100644
--- a/src/lib/snippets.ts
+++ b/src/lib/snippets.ts
@@ -11,6 +11,14 @@ const strState = makeState()
strState.setState('foo')
console.log(strState.getState()) // foo`
+export const bqvz = `// Declare a generic function
+function genericFunc() {
+ // You can use T here
+}
+
+// Call it: T will be number
+genericFunc()`
+
export const brze = `function makeState() {
let state: S
@@ -127,6 +135,14 @@ console.log(strState.getState())
export const jdhu = `// It sets S as number
makeState()`
+export const kbld = `// Limits the type of T
+function genericFunc()
+
+// Success
+genericFunc()
+// Error
+genericFunc()`
+
export const kiyi = `// Confused by generics code like this?
function getProperty(
obj: T,
@@ -155,33 +171,33 @@ export const nnyl = `function makeState() {
return { getState, setState }
}`
-export const nuzz = `interface State {
- value?: V
- author?: A
-}
-
-function makeState<
- V extends number | string,
- A extends string
+export const nuzz = `function makeState<
+ A extends number | string,
+ B extends number | string
>() {
- let state: State = {}
+ let state: [A, B]
function getState() {
return state
}
- function setState(value: V, author: A) {
- state.value = value
- state.author = author
+ function setState(first: A, second: B) {
+ state = [first, second]
}
return { getState, setState }
}
-const state = makeState()
+const state = makeState()
state.setState(1, 'cat')
console.log(state.getState())`
+export const nyih = `// Set the default type of T
+function genericFunc()
+
+// T will be number inside the function
+genericFunc()`
+
export const osaa = `function makeState() {
// Change to string
let state: string
@@ -203,6 +219,20 @@ const { getState, setState } = makeState()
setState('foo')
console.log(getState())`
+export const pjcw = `// Set default value of x
+function regularFunc(x = 2)
+
+// x will be 2 inside the function
+regularFunc()`
+
+export const qini = `// Specify x to be number
+function regularFunc(x: number)
+
+// Success
+regularFunc(1)
+// Error
+regularFunc('foo')`
+
export const qqic = `// Doesn't work because the created state…
const numAndStrState = makeState()
@@ -257,6 +287,14 @@ console.log(getState())
setState(2)
console.log(getState())`
+export const wpru = `// Declare a regular function
+function regularFunc(x: any) {
+ // You can use x here
+}
+
+// Call it: x will be 1
+regularFunc(1)`
+
export const xeax = `const { getState, setState } = makeState()
setState('foo')
diff --git a/src/lib/theme/colors.ts b/src/lib/theme/colors.ts
index 9dd545a..8726d59 100644
--- a/src/lib/theme/colors.ts
+++ b/src/lib/theme/colors.ts
@@ -4,13 +4,13 @@ export const allColors = {
lightYellow2: '#FFE8BF',
lightPink1: '#FFF2E4',
lightPink2: '#FFE7DD',
- lightGreen: '#DFE9CE',
+ lightGreen: '#E4EDD5',
brown: '#806538',
lightBrown: '#E9D1AC',
darkOrange: '#EC9602',
pink: '#FFD9CC',
white: '#FFFFFF',
- white75: 'rgba(255, 255, 255, 0.75)',
+ white85: 'rgba(255, 255, 255, 0.85)',
paleGreen: '#C8DCC7',
red: '#DB4003',
yellowHighlight: '#FFFF00'
diff --git a/src/pages/generics.tsx b/src/pages/generics.tsx
index 8236794..6728544 100644
--- a/src/pages/generics.tsx
+++ b/src/pages/generics.tsx
@@ -1,11 +1,14 @@
import React from 'react'
import PostPage from 'src/components/PostPage'
-import { P, Code, Highlight, Ul, UlLi } from 'src/components/ContentTags'
+import { P, Code, Highlight, Ul, UlLi, Hr } 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'
import RunButtonText from 'src/components/RunButtonText'
+import TwitterLink from 'src/components/TwitterLink'
+import { articlesData } from 'src/lib/articles'
+import { baseUrl } from 'src/lib/meta'
const Page = () => (
(
Note: If you already understand generics, you
won’t find anything new in this tutorial. However,{' '}
-
+
you might know someone (maybe your colleague or your Twitter
follower) who’s struggling with generics
. If so, I’d appreciate it if you could share this article with
- them.
+ them.{' '}
+
+ Click here to tweet this article.
+
>
)
@@ -153,7 +162,7 @@ const Page = () => (
/>
It failed to compile because setState() expects a
- number as its argument.
+ number:
(
makeState() is now defined as{' '}
makeState<S>(). You can think of{' '}
- <S> as another argument that you have to pass
- in when you call the function. But instead of passing a value, you
- pass a type to it. It’s a type argument.
+ <S> as another thing that you have to pass in
+ when you call the function. But instead of passing a value, you
+ pass a type to it.
For example, you can pass the type number as{' '}
@@ -368,7 +377,7 @@ const Page = () => (
The solution:{' '}
When you declare makeState(), you change the type
- argument <S> to{' '}
+ parameter <S> to{' '}
<S extends number | string>
. That’s the only change you need to make.
@@ -413,7 +422,7 @@ const Page = () => (
It resulted in an error, which is what we want!
As you just saw, you can specify what’s allowed for the type
- argument(s) of a generic function.
+ parameter(s) of a generic function.
- It can be annoying to specify type arguments like{' '}
+ It can be annoying to specify types like{' '}
<number> or <string> every
time you call makeState().
@@ -431,10 +440,10 @@ const Page = () => (
So here’s an idea:{' '}
Can we make it so that <number> is the
- default type argument of makeState()?
+ default type parameter of makeState()?
{' '}
- We want to make it so that, if the type argument is missing, it’s
- set as number by default.
+ We want to make it so that, if the type is missing, it’s set as{' '}
+ number by default.
+ We are about two-thirds of the way through this article.
+ Before we continue, let’s do a quick recap.
+
+
+ What you should remember is that,{' '}
+
+ generics are just like regular function parameters.
+ {' '}
+ The difference is that{' '}
+
+ regular function parameters deal with values, but generics deal
+ with types.
+
+
+
+
+ Example 1: For example, here’s a regular function
+ that takes any value:
+
+
+
+ Similarly, you can declare a generic function with a type
+ parameter:
+
+
+
+
+ Example 2: In regular functions, you can specify
+ the type of a parameter like this:
+
+
+
+ Similarly, you can specify what’s allowed for the type parameter
+ of a generic function:
+
+
+
+
+ Example 3: In regular functions, you can specify
+ the default value of a parameter like this:
+
+
+
+ Similarly, you can specify the default type for a generic
+ function:
+
+
+
+
+ Generics are not scary. They’re like regular function parameters,
+ but instead of values, it deals with types. If you understood this
+ much, you’re good to go!
+
+ >
+ )
+ },
underConstructionCard
]}
/>
From 5a07d340a584a8a4df7e727dec4f48776aca28aa Mon Sep 17 00:00:00 2001
From: Shu Uesugi
Date: Thu, 21 Nov 2019 11:22:51 -0800
Subject: [PATCH 3/3] Modify tweet link
---
src/pages/generics.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/pages/generics.tsx b/src/pages/generics.tsx
index 6728544..b7e46a4 100644
--- a/src/pages/generics.tsx
+++ b/src/pages/generics.tsx
@@ -61,12 +61,12 @@ const Page = () => (
follower) who’s struggling with generics
. If so, I’d appreciate it if you could share this article with
- them.{' '}
+ them. You can{' '}
- Click here to tweet this article.
+ click here to tweet this article.
>