11import * as fs from 'fs' ;
22import * as path from 'path' ;
3+ import { EOL } from 'os' ;
34import { promisify } from 'util' ;
45import * as gm from 'gray-matter' ;
56import * as hb from 'handlebars' ;
@@ -11,6 +12,17 @@ const readFile = promisify(fs.readFile);
1112const writeFile = promisify ( fs . writeFile ) ;
1213
1314
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+
1426const API_BASE = 'https://api.sendgrid.com/v3' ;
1527type SingleSendParams = {
1628 html : string ,
@@ -52,6 +64,7 @@ type Options = {
5264 listId ?: string ,
5365 suppressionGroupId ?: number ,
5466 siteYaml ?: string ,
67+ subject ?: string ,
5568} ;
5669
5770async function loadTemplate ( path ?: string , options ?: CompileOptions ) {
@@ -65,6 +78,7 @@ function splitTitleFromName(basename: string) {
6578 return [ m [ 0 ] , basename . slice ( m [ 0 ] . length ) ] ;
6679}
6780
81+ type PathContext = ReturnType < typeof contextFromPath > ;
6882function contextFromPath ( filepath : string ) {
6983 const basename = path . basename ( filepath ) ;
7084 const [ title , ext ] = splitTitleFromName ( basename ) ;
@@ -87,21 +101,31 @@ function contextFromPath(filepath: string) {
87101 } ;
88102}
89103
90- function postUrl ( post : ReturnType < typeof contextFromPath > , site : any ) {
104+ function postUrl ( post : PathContext , site : any ) {
91105 const siteUrl = site . url ;
92106 const basePath = site . baseurl ?? '' ;
93107
94108 return `${ siteUrl } ${ basePath } /${ post . year } /${ post . month } /${ post . day } /${ post . slug } .html` ;
95109}
96110
111+ type PostContext = PathContext &
112+ { url : string } &
113+ { [ k in string ] : any } ;
114+
97115function postContext ( data : any , path : string , site ?: any ) {
98116 const post = contextFromPath ( path ) ;
99117
100118 return Object . assign ( { url : site ? postUrl ( post , site ) : '' } ,
101- post , data ) ;
119+ post , data ) as PostContext ;
102120}
103121
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 } > {
105129 if ( ! path )
106130 return { } ;
107131
@@ -125,7 +149,7 @@ async function render(opts: Options) {
125149 } ) ;
126150
127151 const template = await pTemplate ;
128- const context = Object . assign ( {
152+ const context : TemplateContext = Object . assign ( {
129153 content : rendered ,
130154 post : postContext ( data , opts . path , site ) ,
131155 site,
@@ -138,23 +162,41 @@ async function render(opts: Options) {
138162 } ;
139163}
140164
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+
141178async function run ( options : Options ) {
142179 const { text, context } = await render ( options ) ;
143180 // console.log(context);
144181
145182 if ( options . output ) {
146183 await writeFile ( options . output , text ) ;
147184 } else if ( options . apiKey ) {
185+ const sendAt = getSendDate ( context ) ;
148186 const response = await singleSend ( {
149187 html : text ,
150188 listId : options . listId ,
151189 suppressionGroup : options . suppressionGroupId ,
152190 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 ) ,
155193 } ) ;
156194
195+ const url = response . headers . get ( 'location' ) ;
157196 console . log ( response . status , response . statusText , response . headers , await response . text ( ) ) ;
197+
198+ setOutput ( 'send_date' , sendAt . toISOString ( ) ) ;
199+ setOutput ( 'single_send_url' , url ) ;
158200 } else {
159201 console . log ( text ) ;
160202 }
@@ -170,6 +212,7 @@ async function runAction() {
170212 INPUT_OUT_PATH : outPath ,
171213 INPUT_SUPPRESSION_GROUP_ID : suppressionGroupId ,
172214 INPUT_SITE_YAML : siteYaml ,
215+ INPUT_SUBJECT_FORMAT : subject = '%s' ,
173216 } = process . env ;
174217
175218 if ( ! path ) {
@@ -188,6 +231,7 @@ async function runAction() {
188231 listId : listId ,
189232 suppressionGroupId : suppressionGroupId ? parseInt ( suppressionGroupId ) : undefined ,
190233 siteYaml,
234+ subject,
191235 } ) ;
192236}
193237
0 commit comments