Added support for image attachments by converting Markdown image tags into CIDs and adding the corresponding attachments. At the moment all image tags are parsed as attachments -- external resources, such as http://, are not respected. Default newsletter now depends on markdown-it-anchor and markdown-it-deflist -- this should probably not be the default.
parent
6ba8f81431
commit
174eeadecf
3
app.js
3
app.js
|
@ -152,7 +152,8 @@ Newsletter.prototype.send = function() {
|
||||||
from: this.options.from,
|
from: this.options.from,
|
||||||
subject: this.temp.subject,
|
subject: this.temp.subject,
|
||||||
text: (this.temp.text ? this.temp.text : ''),
|
text: (this.temp.text ? this.temp.text : ''),
|
||||||
html: (this.temp.html ? this.temp.html : '')
|
html: (this.temp.html ? this.temp.html : ''),
|
||||||
|
attachments: (this.temp.attachments ? this.temp.attachments : [])
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
/* Method: archive(letter, file)
|
/* Method: archive(letter, file)
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"options": {
|
"options": {
|
||||||
"from": "Polymail <user@domain>",
|
"from": "Polymail <user@domain>",
|
||||||
"heading": "Polymail"
|
"heading": "[Polymail]",
|
||||||
|
"name": "Polymail"
|
||||||
},
|
},
|
||||||
"subscribers": [
|
"subscribers": [
|
||||||
"user@domain"
|
"user@domain"
|
||||||
|
|
|
@ -11,12 +11,30 @@ var md = require('markdown-it')({
|
||||||
typographer: true
|
typographer: true
|
||||||
});
|
});
|
||||||
md.use(require('markdown-it-header-sections'));
|
md.use(require('markdown-it-header-sections'));
|
||||||
|
md.use(require('markdown-it-deflist'));
|
||||||
|
|
||||||
|
var defaultRender = md.renderer.rules.image;
|
||||||
|
md.renderer.rules.image = function(tokens, idx, options, env, self) {
|
||||||
|
var token = tokens[idx],
|
||||||
|
aIndex = token.attrIndex('src');
|
||||||
|
|
||||||
|
newsletter.temp.attachments.push({
|
||||||
|
filename: token.attrs[aIndex][1],
|
||||||
|
path: '',
|
||||||
|
cid: token.attrs[aIndex][1]
|
||||||
|
});
|
||||||
|
token.attrs[aIndex][1] = 'cid:'+token.attrs[aIndex][1];
|
||||||
|
|
||||||
|
return defaultRender(tokens, idx, options, env, self);
|
||||||
|
};
|
||||||
|
|
||||||
/* ==== NEWSLETTER ========================================================== */
|
/* ==== NEWSLETTER ========================================================== */
|
||||||
// our custom build step
|
// our custom build step
|
||||||
newsletter.build = function(file, options, cb) {
|
newsletter.build = function(file, options, cb) {
|
||||||
// clear potential old newsletter
|
// clear potential old newsletter
|
||||||
newsletter.temp = {};
|
newsletter.temp = {
|
||||||
|
attachments: []
|
||||||
|
};
|
||||||
// merge passed options with newsletter defaults
|
// merge passed options with newsletter defaults
|
||||||
var opts = polymail.mergeObjects(newsletter.options, options);
|
var opts = polymail.mergeObjects(newsletter.options, options);
|
||||||
// read our provided content file
|
// read our provided content file
|
||||||
|
@ -28,6 +46,12 @@ newsletter.build = function(file, options, cb) {
|
||||||
var md_result = md_template(opts);
|
var md_result = md_template(opts);
|
||||||
// convert our content md into html
|
// convert our content md into html
|
||||||
opts.content = md.render(opts.content.toString());
|
opts.content = md.render(opts.content.toString());
|
||||||
|
// at this point attachments should be populated with all pertinent attachments - let's modify it to make all paths relative to this file's directory
|
||||||
|
var path = file;
|
||||||
|
file = file.replace(/\.[^/.]+$/, "");
|
||||||
|
for (var i = 0; i < newsletter.temp.attachments.length; i++) {
|
||||||
|
newsletter.temp.attachments[i].path = file+'/'+newsletter.temp.attachments[i].filename;
|
||||||
|
}
|
||||||
// read our html template and build it
|
// read our html template and build it
|
||||||
var html_source = fs.readFileSync(__dirname+'/templates/html.dot');
|
var html_source = fs.readFileSync(__dirname+'/templates/html.dot');
|
||||||
var html_template = doT.template(html_source);
|
var html_template = doT.template(html_source);
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dot": "^1.0.3",
|
"dot": "^1.0.3",
|
||||||
"markdown-it": "^5.0.2",
|
"markdown-it": "^5.0.2",
|
||||||
|
"markdown-it-anchor": "^2.3.3",
|
||||||
|
"markdown-it-deflist": "^2.0.0",
|
||||||
"markdown-it-header-sections": "^0.2.2"
|
"markdown-it-header-sections": "^0.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,64 @@
|
||||||
<head>
|
<head>
|
||||||
<title>{{=it.heading || ''}} {{=it.title || ''}}</title>
|
<title>{{=it.heading || ''}} {{=it.title || ''}}</title>
|
||||||
<style>
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #f3f3d8;
|
||||||
|
color: #0c0c27;
|
||||||
|
font-size: 12pt;
|
||||||
|
font-family: "Trebuchet MS", Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
a,a:visited {
|
||||||
|
color: #b87602;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
p,ul,li {
|
||||||
|
color: #0c0c27;
|
||||||
|
font-size: 12pt;
|
||||||
|
font-family: helvetica, sans-serif;
|
||||||
|
}
|
||||||
p {
|
p {
|
||||||
color: #111;
|
padding-left: 1em;
|
||||||
|
margin-top: 0.25em;
|
||||||
|
line-height: 1.3em;
|
||||||
|
width: 35em;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
max-width: 30%;
|
||||||
|
float: left;
|
||||||
|
padding: 0 1em 0.5em 0;
|
||||||
|
}
|
||||||
|
h1 span {
|
||||||
|
color: #4c4c67;
|
||||||
|
margin-left: 0.5em;
|
||||||
|
font-size: 16pt;
|
||||||
|
}
|
||||||
|
h1 small {
|
||||||
|
color: #9c9cB7;
|
||||||
|
float: right;
|
||||||
|
font-size: 14pt;
|
||||||
|
}
|
||||||
|
h1,h2,h3,h4,h5,h6,h7,h8,h9 { width: 75%; font-family: 'Arial Black', 'Arial Bold', 'Gadget', sans-serif; border-bottom: 0.1em solid #1c1c37; color: #1c1c37; margin-bottom: 0.25em; }
|
||||||
|
h1 { width: 100%; font-size: 24pt; margin-bottom: 1em; margin-top: 0; border: 0 }
|
||||||
|
h2 { color: #3c3c57; border-color: #3c3c57; font-size: 20pt; }
|
||||||
|
h3 { color: #5c5c77; border-color: #5c5c77; font-size: 18pt; }
|
||||||
|
h4 { color: #6c6c87; border-color: #6c6c87; font-size: 14pt; }
|
||||||
|
h5 { color: #7c7c97; border-color: #7c7c97; font-size: 12pt; }
|
||||||
|
section { margin-left: 0.25em; margin-top: 0; }
|
||||||
|
dt {
|
||||||
|
float: left;
|
||||||
|
clear: left;
|
||||||
|
width: 10em;
|
||||||
|
text-align: left;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
dd {
|
||||||
|
margin: 0 0 0 10.5em;
|
||||||
|
padding: 0 0 0.5em 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>{{=it.heading || ''}} {{=it.title || ''}}</h1>
|
<h1>{{=it.name || '' }} <span>{{=it.letter || ''}}</span> <small>{{=it.date || ''}}</h1>
|
||||||
<small>{{=it.timestamp}}</small>
|
|
||||||
{{=it.content || ''}}
|
{{=it.content || ''}}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
# {{=it.heading || ''}} {{=it.title || ''}} {{=it.timestamp || ''}}
|
# {{=it.name || ''}} {{=it.letter || ''}} -- {{=it.date || ''}}
|
||||||
|
|
||||||
{{=it.content || ''}}
|
{{=it.content || ''}}
|
||||||
|
|
Loading…
Reference in New Issue