1
1
import * as fs from 'fs' ;
2
2
import * as path from 'path' ;
3
+ import { EOL } from 'os' ;
3
4
import { promisify } from 'util' ;
4
5
import * as gm from 'gray-matter' ;
5
6
import * as hb from 'handlebars' ;
@@ -11,6 +12,17 @@ const readFile = promisify(fs.readFile);
11
12
const writeFile = promisify ( fs . writeFile ) ;
12
13
13
14
15
+ function escapeData ( s : string ) : string {
16
+ return s
17
+ . replace ( / % / g, '%25' )
18
+ . replace ( / \r / g, '%0D' )
19
+ . replace ( / \n / g, '%0A' )
20
+ }
21
+
22
+ function setOutput ( key : string , val : string ) {
23
+ process . stdout . write ( `::set-output name=${ key } ::${ escapeData ( val ) } ` + EOL ) ;
24
+ }
25
+
14
26
const API_BASE = 'https://api.sendgrid.com/v3' ;
15
27
type SingleSendParams = {
16
28
html : string ,
@@ -52,6 +64,7 @@ type Options = {
52
64
listId ?: string ,
53
65
suppressionGroupId ?: number ,
54
66
siteYaml ?: string ,
67
+ subject ?: string ,
55
68
} ;
56
69
57
70
async function loadTemplate ( path ?: string , options ?: CompileOptions ) {
@@ -65,6 +78,7 @@ function splitTitleFromName(basename: string) {
65
78
return [ m [ 0 ] , basename . slice ( m [ 0 ] . length ) ] ;
66
79
}
67
80
81
+ type PathContext = ReturnType < typeof contextFromPath > ;
68
82
function contextFromPath ( filepath : string ) {
69
83
const basename = path . basename ( filepath ) ;
70
84
const [ title , ext ] = splitTitleFromName ( basename ) ;
@@ -87,21 +101,31 @@ function contextFromPath(filepath: string) {
87
101
} ;
88
102
}
89
103
90
- function postUrl ( post : ReturnType < typeof contextFromPath > , site : any ) {
104
+ function postUrl ( post : PathContext , site : any ) {
91
105
const siteUrl = site . url ;
92
106
const basePath = site . baseurl ?? '' ;
93
107
94
108
return `${ siteUrl } ${ basePath } /${ post . year } /${ post . month } /${ post . day } /${ post . slug } .html` ;
95
109
}
96
110
111
+ type PostContext = PathContext &
112
+ { url : string } &
113
+ { [ k in string ] : any } ;
114
+
97
115
function postContext ( data : any , path : string , site ?: any ) {
98
116
const post = contextFromPath ( path ) ;
99
117
100
118
return Object . assign ( { url : site ? postUrl ( post , site ) : '' } ,
101
- post , data ) ;
119
+ post , data ) as PostContext ;
102
120
}
103
121
104
- async function siteContext ( path ?: string ) {
122
+ type TemplateContext = {
123
+ content : string ,
124
+ post : PostContext ,
125
+ site : { [ k in string ] : any } ,
126
+ } & { [ k in string ] : any } ;
127
+
128
+ async function siteContext ( path ?: string ) : Promise < { [ k in string ] : any } > {
105
129
if ( ! path )
106
130
return { } ;
107
131
@@ -125,7 +149,7 @@ async function render(opts: Options) {
125
149
} ) ;
126
150
127
151
const template = await pTemplate ;
128
- const context = Object . assign ( {
152
+ const context : TemplateContext = Object . assign ( {
129
153
content : rendered ,
130
154
post : postContext ( data , opts . path , site ) ,
131
155
site,
@@ -138,23 +162,41 @@ async function render(opts: Options) {
138
162
} ;
139
163
}
140
164
165
+ function getSendDate ( c : TemplateContext ) {
166
+ let date = c . post . date ;
167
+ if ( date . getTime ( ) <= Date . now ( ) ) {
168
+ const today = new Date ( ) ;
169
+ date = new Date ( today . getFullYear ( ) ,
170
+ today . getMonth ( ) ,
171
+ today . getDate ( ) + 1 ) ;
172
+ }
173
+
174
+ date . setHours ( 15 ) ;
175
+ return date ;
176
+ }
177
+
141
178
async function run ( options : Options ) {
142
179
const { text, context } = await render ( options ) ;
143
180
// console.log(context);
144
181
145
182
if ( options . output ) {
146
183
await writeFile ( options . output , text ) ;
147
184
} else if ( options . apiKey ) {
185
+ const sendAt = getSendDate ( context ) ;
148
186
const response = await singleSend ( {
149
187
html : text ,
150
188
listId : options . listId ,
151
189
suppressionGroup : options . suppressionGroupId ,
152
190
token : options . apiKey ,
153
- sendAt : new Date ( Date . now ( ) + 60000 ) ,
154
- subject : `Test Newsletter: ${ context . post . title } ` ,
191
+ sendAt,
192
+ subject : ( options . subject ?? '%s' ) . replace ( '%s' , context . post . title ) ,
155
193
} ) ;
156
194
195
+ const url = response . headers . get ( 'location' ) ;
157
196
console . log ( response . status , response . statusText , response . headers , await response . text ( ) ) ;
197
+
198
+ setOutput ( 'send_date' , sendAt . toISOString ( ) ) ;
199
+ setOutput ( 'single_send_url' , url ) ;
158
200
} else {
159
201
console . log ( text ) ;
160
202
}
@@ -170,6 +212,7 @@ async function runAction() {
170
212
INPUT_OUT_PATH : outPath ,
171
213
INPUT_SUPPRESSION_GROUP_ID : suppressionGroupId ,
172
214
INPUT_SITE_YAML : siteYaml ,
215
+ INPUT_SUBJECT_FORMAT : subject = '%s' ,
173
216
} = process . env ;
174
217
175
218
if ( ! path ) {
@@ -188,6 +231,7 @@ async function runAction() {
188
231
listId : listId ,
189
232
suppressionGroupId : suppressionGroupId ? parseInt ( suppressionGroupId ) : undefined ,
190
233
siteYaml,
234
+ subject,
191
235
} ) ;
192
236
}
193
237
0 commit comments