Skip to content

Commit 152c317

Browse files
committed
wip
1 parent b43a849 commit 152c317

16 files changed

+546
-87
lines changed

CHANGELOG.md

+57-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,68 @@
11
# CHANGELOG
22

3-
**v0.1.0-alpha.3:**
3+
## v0.1.0-alpha.4:
4+
5+
### Breaking Changes
6+
7+
- `ViewInBrowser` component now does not accept any params
8+
- Function definition for `Image` has changed:
9+
10+
```go
11+
// Old ❌
12+
templateless.NewContent().
13+
Image(
14+
"https://example.com/image.jpg",
15+
Some("https://example.com"),
16+
Some(200), // Width
17+
Some(100), // Height
18+
Some("Alt Text"),
19+
).
20+
Build()
21+
22+
// New (just image) ✅
23+
templateless.NewContent().
24+
Image("https://example.com/image.jpg").
25+
Build()
26+
27+
// New (clickable image with custom attributes) ✅
28+
url := "https://example.com"
29+
width := 300
30+
height := 200
31+
alt := "Alt text"
32+
templateless.NewContent().
33+
Component(
34+
components.NewImage(
35+
"https://placekitten.com/300/200",
36+
&url,
37+
&width,
38+
&height,
39+
&alt,
40+
),
41+
).
42+
Build()
43+
```
44+
45+
### New Features
46+
- New social icons: `Mastodon` and `Rss`
47+
- New `StoreBadges` component
48+
- New `QrCode` component
49+
- New `Signature` component
50+
- New [examples](examples)
51+
52+
### Enhancements
53+
- Updated README
54+
- Dependency updates
55+
56+
## v0.1.0-alpha.3:
457
- `README.md`: notice about test mode
558
- Support for test mode logging
659

7-
**v0.1.0-alpha.2:**
60+
## v0.1.0-alpha.2:
861
- `README.md` cleanup (listing of components)
962
- Added `examples/confirm_email`
1063
- Renamed `SetFooter()` to `Footer()`
1164

12-
**v0.1.0-alpha.1:**
65+
## v0.1.0-alpha.1:
1366
- Introduced `CHANGELOG.md`
1467
- Introduced new services as social icons:
1568
- `Phone` (converts into a link with `tel:` prefix)
@@ -24,5 +77,5 @@
2477
- `Threads`
2578
- `Telegram`
2679

27-
**v0.1.0-alpha.0:**
80+
## v0.1.0-alpha.0:
2881
- Initial implementation

README.md

+111-13
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ It's perfect for SaaS, web apps, mobile apps, scripts and anywhere you have to s
4040
Use go get:
4141

4242
```bash
43-
go get github.com/templateless/[email protected].3
43+
go get github.com/templateless/[email protected].4
4444
```
4545

4646
Then import the package into your own code:
@@ -85,10 +85,8 @@ func main() {
8585
Content(*content).
8686
Build()
8787

88-
result, _ := templateless.NewTemplateless("<YOUR_API_KEY>").
88+
templateless.NewTemplateless("<YOUR_API_KEY>").
8989
Send(*email)
90-
91-
log.Println(result)
9290
}
9391
```
9492

@@ -159,8 +157,7 @@ Link component adds an anchor tag. This is the same as a text component with the
159157

160158
```go
161159
templateless.NewContent().
162-
Link("Confirm Email", "https://example.com/confirm?token=XYZ"). // or...
163-
Text("[Confirm Email](https://example.com/confirm?token=XYZ)").
160+
Link("Confirm Email", "https://example.com/confirm?token=XYZ").
164161
Build()
165162
```
166163

@@ -181,13 +178,25 @@ templateless.NewContent().
181178
Image component will link to an image within your email. Keep in mind that a lot of email clients will prevent images from being loaded automatically for privacy reasons.
182179

183180
```go
181+
// Simple
182+
templateless.NewContent().
183+
Image("https://placekitten.com/300/200").
184+
Build()
185+
186+
// Clickable & with attributes
187+
url := "https://example.com"
188+
width := 300
189+
height := 200
190+
alt := "Alt text"
184191
templateless.NewContent().
185-
Image(
186-
"https://placekitten.com/300/200", // where the image is hosted
187-
"https://example.com", // [optional] link url, if you want it to be clickable
188-
300, // [optional] width
189-
200, // [optional] height
190-
"Alt text", // [optional] alternate text
192+
Component(
193+
components.NewImage(
194+
"https://placekitten.com/300/200",
195+
&url,
196+
&width,
197+
&height,
198+
&alt,
199+
),
191200
).
192201
Build()
193202
```
@@ -249,6 +258,8 @@ templateless.NewContent().
249258
*components.NewSocialItem(components.Snapchat, "Username"),
250259
*components.NewSocialItem(components.Threads, "Username"),
251260
*components.NewSocialItem(components.Telegram, "Username"),
261+
*components.NewSocialItem(components.Mastodon, "@[email protected]"),
262+
*components.NewSocialItem(components.Rss, "https://example.com/blog"),
252263
}).
253264
Build()
254265
```
@@ -264,11 +275,98 @@ You can optionally provide the text for the link. If none is provided, default i
264275

265276
```go
266277
templateless.NewContent().
267-
ViewInBrowser("Read Email in Browser").
278+
ViewInBrowser().
279+
Build()
280+
```
281+
282+
</details>
283+
<details><summary>Store Badges</summary>
284+
285+
Link to your mobile apps via store badges:
286+
287+
```go
288+
templateless.NewContent().
289+
StoreBadges([]components.StoreBadgeItem{
290+
*components.NewStoreBadgeItem(components.AppStore, "https://apps.apple.com/us/app/example/id1234567890"),
291+
*components.NewStoreBadgeItem(components.GooglePlay, "https://play.google.com/store/apps/details?id=com.example"),
292+
*components.NewStoreBadgeItem(components.MicrosoftStore, "https://apps.microsoft.com/detail/example"),
293+
}).
268294
Build()
269295
```
270296

271297
</details>
298+
<details><summary>QR Code</summary>
299+
300+
You can also generate QR codes on the fly. They will be shown as images inside the email.
301+
302+
Here are all the supported data types:
303+
304+
```go
305+
// URL
306+
templateless.NewContent().
307+
QrCode("https://example.com").
308+
Build()
309+
310+
// Email
311+
templateless.NewContent().
312+
Component(components.QrCodeEmail("[email protected]")).
313+
Build()
314+
315+
// Phone
316+
templateless.NewContent().
317+
Component(components.QrCodePhone("123-456-7890")).
318+
Build()
319+
320+
// SMS / Text message
321+
templateless.NewContent().
322+
Component(components.QrCodeSMS("123-456-7890")).
323+
Build()
324+
325+
// Geo coordinates
326+
templateless.NewContent().
327+
Component(components.QrCodeCoordinates(37.773972, -122.431297)).
328+
Build()
329+
330+
// Crypto address (for now only Bitcoin and Ethereum are supported)
331+
templateless.NewContent().
332+
Component(components.QrCodeCryptocurrencyAddress(components.Bitcoin, "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa")).
333+
Build()
334+
335+
// You can also encode any binary data
336+
templateless.NewContent().
337+
Component(components.NewQrCode([]byte{1, 2, 3})).
338+
Build()
339+
```
340+
341+
</details>
342+
<details><summary>Signature</summary>
343+
344+
Generated signatures can be added to your emails to give a bit of a personal touch. This will embed an image with your custom text using one of several available fonts:
345+
346+
```go
347+
// Signature with a default font
348+
templateless.NewContent().
349+
Signature("John Smith").
350+
Build()
351+
352+
// Signature with a custom font
353+
templateless.NewContent().
354+
Component(components.NewSignature("John Smith", &components.ReenieBeanie)).
355+
Build()
356+
```
357+
358+
These are the available fonts:
359+
360+
- `ReenieBeanie` [preview →](https://fonts.google.com/specimen/Reenie+Beanie)
361+
- `MeowScript` [preview →](https://fonts.google.com/specimen/Meow+Script)
362+
- `Caveat` [preview →](https://fonts.google.com/specimen/Caveat)
363+
- `Zeyada` [preview →](https://fonts.google.com/specimen/Zeyada)
364+
- `Petemoss` [preview →](https://fonts.google.com/specimen/Petemoss)
365+
366+
Signature should not exceed 64 characters. Only alphanumeric characters and most common symbols are allowed.
367+
368+
</details>
369+
272370

273371
---
274372

collection.go

+24-4
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ func (c *Collection) Button(text, url string) *Collection {
2727
return c
2828
}
2929

30-
func (c *Collection) Image(src string, url string, width, height int, alt string) *Collection {
31-
c.Components = append(c.Components, components.NewImage(src, alt, url, width, height))
30+
func (c *Collection) Image(src string) *Collection {
31+
c.Components = append(c.Components, components.NewImage(src, nil, nil, nil, nil))
3232
return c
3333
}
3434

@@ -52,8 +52,28 @@ func (c *Collection) Text(text string) *Collection {
5252
return c
5353
}
5454

55-
func (c *Collection) ViewInBrowser(text string) *Collection {
56-
c.Components = append(c.Components, components.NewViewInBrowser(text))
55+
func (c *Collection) ViewInBrowser() *Collection {
56+
c.Components = append(c.Components, components.NewViewInBrowser(nil))
57+
return c
58+
}
59+
60+
func (c *Collection) QrCode(url string) *Collection {
61+
c.Components = append(c.Components, components.QrCodeURL(url))
62+
return c
63+
}
64+
65+
func (c *Collection) StoreBadges(data []components.StoreBadgeItem) *Collection {
66+
c.Components = append(c.Components, components.NewStoreBadges(data))
67+
return c
68+
}
69+
70+
func (c *Collection) Signature(text string) *Collection {
71+
c.Components = append(c.Components, components.NewSignature(text, nil))
72+
return c
73+
}
74+
75+
func (c *Collection) Component(component components.Component) *Collection {
76+
c.Components = append(c.Components, component)
5777
return c
5878
}
5979

components/components.go

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ const (
1111
ComponentIdSocials ComponentId = "SOCIALS"
1212
ComponentIdText ComponentId = "TEXT"
1313
ComponentIdViewInBrowser ComponentId = "VIEW_IN_BROWSER"
14+
ComponentIdStoreBadges ComponentId = "STORE_BADGES"
15+
ComponentIdQrCode ComponentId = "QR_CODE"
16+
ComponentIdSignature ComponentId = "SIGNATURE"
1417
)
1518

1619
type Component interface {

components/image.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ package components
33
type Image struct {
44
Id ComponentId `json:"id"`
55
Src string `json:"src"`
6-
Alt string `json:"alt"`
7-
Width int `json:"width"`
8-
Height int `json:"height"`
9-
URL string `json:"url"`
6+
Alt *string `json:"alt"`
7+
Width *int `json:"width"`
8+
Height *int `json:"height"`
9+
URL *string `json:"url"`
1010
}
1111

12-
func NewImage(src, alt, url string, width, height int) *Image {
12+
func NewImage(src string, url *string, width, height *int, alt *string) *Image {
1313
return &Image{
1414
Id: ComponentIdImage,
1515
Src: src,

components/qr_code.go

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package components
2+
3+
import (
4+
"encoding/base64"
5+
"fmt"
6+
)
7+
8+
type Cryptocurrency string
9+
10+
const (
11+
Bitcoin Cryptocurrency = "bitcoin"
12+
Ethereum Cryptocurrency = "ethereum"
13+
)
14+
15+
type QrCode struct {
16+
Id ComponentId `json:"id"`
17+
Data string `json:"data"`
18+
}
19+
20+
func NewQrCode(data []byte) *QrCode {
21+
return &QrCode{
22+
Id: ComponentIdQrCode,
23+
Data: base64.StdEncoding.EncodeToString(data),
24+
}
25+
}
26+
27+
func QrCodeEmail(email string) *QrCode {
28+
return NewQrCode([]byte(fmt.Sprintf("mailto:%s", email)))
29+
}
30+
31+
func QrCodeURL(url string) *QrCode {
32+
return NewQrCode([]byte(url))
33+
}
34+
35+
func QrCodePhone(phone string) *QrCode {
36+
return NewQrCode([]byte(fmt.Sprintf("tel:%s", phone)))
37+
}
38+
39+
func QrCodeSMS(text string) *QrCode {
40+
return NewQrCode([]byte(fmt.Sprintf("smsto:%s", text)))
41+
}
42+
43+
func QrCodeCoordinates(lat, lng float64) *QrCode {
44+
return NewQrCode([]byte(fmt.Sprintf("geo:%f,%f", lat, lng)))
45+
}
46+
47+
func QrCodeCryptocurrencyAddress(crypto Cryptocurrency, address string) *QrCode {
48+
return NewQrCode([]byte(fmt.Sprintf("%s:%s", crypto, address)))
49+
}

components/signature.go

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package components
2+
3+
type SignatureFont string
4+
5+
const (
6+
ReenieBeanie SignatureFont = "REENIE_BEANIE"
7+
MeowScript SignatureFont = "MEOW_SCRIPT"
8+
Caveat SignatureFont = "CAVEAT"
9+
Zeyada SignatureFont = "ZEYADA"
10+
Petemoss SignatureFont = "PETEMOSS"
11+
)
12+
13+
type Signature struct {
14+
Id ComponentId `json:"id"`
15+
Text string `json:"text"`
16+
Font *SignatureFont `json:"font"`
17+
}
18+
19+
func NewSignature(text string, font *SignatureFont) *Signature {
20+
return &Signature{
21+
Id: ComponentIdSignature,
22+
Text: text,
23+
Font: font,
24+
}
25+
}

0 commit comments

Comments
 (0)