Fix node-weekly newsletter getting forwarded
* This error is caused by a previous rebase conflict and resolving the conflict caused an important line missing * Revert the change to add CooperPressHandler to the array of newsletter handlers * Updated the test to get the correct handler from email content to prevent such cases
This commit is contained in:
@ -26,6 +26,7 @@ import { ConvertkitHandler } from './newsletters/convertkit-handler'
|
||||
import { RevueHandler } from './newsletters/revue-handler'
|
||||
import { GhostHandler } from './newsletters/ghost-handler'
|
||||
import { parseHTML } from 'linkedom'
|
||||
import { CooperPressHandler } from './newsletters/cooper-press-handler'
|
||||
|
||||
const validateUrlString = (url: string) => {
|
||||
const u = new URL(url)
|
||||
@ -73,6 +74,7 @@ const newsletterHandlers: ContentHandler[] = [
|
||||
new ConvertkitHandler(),
|
||||
new RevueHandler(),
|
||||
new GhostHandler(),
|
||||
new CooperPressHandler(),
|
||||
]
|
||||
|
||||
export const preHandleContent = async (
|
||||
@ -122,21 +124,37 @@ export const preParseContent = async (
|
||||
return undefined
|
||||
}
|
||||
|
||||
export const handleNewsletter = async (
|
||||
input: NewsletterInput
|
||||
): Promise<NewsletterResult | undefined> => {
|
||||
export const getNewsletterHandler = async (input: {
|
||||
postHeader: string
|
||||
from: string
|
||||
unSubHeader: string
|
||||
html: string
|
||||
}): Promise<ContentHandler | undefined> => {
|
||||
const dom = parseHTML(input.html).document
|
||||
for (const handler of newsletterHandlers) {
|
||||
if (await handler.isNewsletter({ ...input, dom })) {
|
||||
return handler.handleNewsletter(input)
|
||||
return handler
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
export const handleNewsletter = async (
|
||||
input: NewsletterInput
|
||||
): Promise<NewsletterResult | undefined> => {
|
||||
const handler = await getNewsletterHandler(input)
|
||||
if (handler) {
|
||||
console.log('handleNewsletter', handler.name, input.title)
|
||||
return handler.handleNewsletter(input)
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
preHandleContent,
|
||||
handleNewsletter,
|
||||
preParseContent,
|
||||
getNewsletterHandler,
|
||||
}
|
||||
|
||||
@ -45,15 +45,15 @@
|
||||
</style>
|
||||
</head>
|
||||
<body style="width: 100%; background-color: white; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; text-rendering: optimizeLegibility; direction: ltr; font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0;">
|
||||
<div id="preview" class="preheader noarchive" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; color: white; font-family: helvetica, arial; line-height: 0px; height: 0px; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; overflow-y: hidden; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0;">Plus Node 16.18.0, an IP info database, turning cron expressions into English, and 2FA with Twilio. | </div>
|
||||
<div id="preview" class="preheader noarchive" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; color: white; font-family: helvetica, arial; line-height: 0px; height: 0px; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; overflow-y: hidden; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0;">Plus choosing the best Node Docker image to use, and a way to embed Node and V8 into JVM apps. | </div>
|
||||
<!--[if (gte mso 9)|(IE)]>
|
||||
<table cellpadding="0" cellspacing="0" align="center" bgcolor="#ffffff" width="600"><tr><td valign="top" style="width: 600px;" bgcolor="#ffffff"><![endif]-->
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" id="main" width="100%" style="table-layout: fixed; font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; max-width: 600px; height: 100% !important; direction: ltr; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px;">
|
||||
<tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse;">
|
||||
<div id="content"> <!-- left/right splitbar -->
|
||||
<table class="el-splitbar" width="100%" cellpadding="0" cellspacing="0" style="border-collapse: collapse;"><tr>
|
||||
<td width="50%" align="left" style="padding-left: 4px; font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse;"><p style="font-size: 12px; color: #999999; text-transform: uppercase; line-height: 1.0em; margin-top: 0.8em; margin-bottom: 0.8em;">#458 — October 13, 2022</p></td>
|
||||
<td width="50%" align="right" style="padding-right: 4px; font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse;"><p style="font-size: 12px; text-transform: uppercase; line-height: 1.0em; margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56o0z9xhskaXR4aYohHPLtwRHfml_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5ouN4IH56AfszUQpxY-2FQ233kp0bjSZhBBVWAB43dgKumQkDW-2BxDFnQIUpvhmEgzSJq-2FMRG00GM7fkZVuPU-2BX8cdg8AGRHUU9Qhw6W67XEMkJVygTdm70Mo9ypNi8N33hgmhM3F6un9s7p1K1Gq-2FunslA-3D-3D" style="text-decoration: none; color: #20824B;">Read on the Web</a></p></td>
|
||||
<td width="50%" align="left" style="padding-left: 4px; font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse;"><p style="font-size: 12px; color: #999999; text-transform: uppercase; line-height: 1.0em; margin-top: 0.8em; margin-bottom: 0.8em;">#459 — October 20, 2022</p></td>
|
||||
<td width="50%" align="right" style="padding-right: 4px; font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse;"><p style="font-size: 12px; text-transform: uppercase; line-height: 1.0em; margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56obSPDXnoBEjufvIqRCEJUf5Uqg_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEkDU3SIXWGeoiU60KFhM-2B-2Bxx5yiL8KKbAV6oFceRi8O1gMc3mdwg5D8FaaM3PublaX24iAcVbn99PzxJaPuVrU6xDWbRovw2UgGTIoEI-2BBO-2B0qzi2wv5c6yJTkUGZOcsJ6xGLXO1BO-2BHSbyZMZV4NMw-3D-3D" style="text-decoration: none; color: #20824B;">Read on the Web</a></p></td>
|
||||
</tr></table>
|
||||
<table id="together" width="100%" align="center" style="text-align: center; border-collapse: collapse; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0;">
|
||||
<tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0;">
|
||||
@ -61,8 +61,8 @@
|
||||
<tr>
|
||||
<td style="vertical-align: middle; text-align: right; text-transform: uppercase; letter-spacing: -0.2px; font-weight: 500; color: #222; font-size: 0.9em; font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; line-height: 1.48em; border-collapse: collapse;">Together with </td>
|
||||
<td style="vertical-align: middle; text-align: left; font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse;">
|
||||
<a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56o-2FofL8qV45mZXO-2Bx2UGhMR-2BEL2eksQgpS5LzPvvH6WGg-3D-3DmCKP_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5o5YIrPGfS0ao-2FM0-2B8PZ0ZaLDd-2BnWtY2qWqIuVb8z0pGBtRWChQEglZvFwt8-2BefVEhdDaOOlTJaQlkAX15gZ-2FVV4RHO99DrEzUaXVAk8dwx7iH16kzSiJif2EMiH-2FCQCRfHyrrdEQnwB0VD-2BvFANLd3A-3D-3D" style="outline: none; text-decoration: none; color: #20824B; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0;">
|
||||
<img src="https://res.cloudinary.com/cpress/image/upload/c_fill,g_auto,w_600,h_110/e_make_transparent/co_white,e_outline:7/lnopbsxefrqqsjq14fvr.png" style="max-width: 90px; outline: none; height: auto; text-decoration: none; line-height: 100%; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0;" width="90" alt="Userfront">
|
||||
<a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56r6zTNF2xDv1ApolVrZ4iZ0HiftFJvNFqLdyt1qEIYOmw-3D-3DnmCs_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiE8NENjWQQqAEHbpzhUjH-2Bckj2r35R2Duk7-2FbrQ0LuGQfAPBldpsN7Qx2BrVm2a-2BFlyBXjJOtG89q3W4OYHxWzTrMPn7O5MODZDWI2rIAvBBT7nuLtOzHRyiixX-2BooIGNPoh5jlbPIXUYA7AdsiNLi8w-3D-3D" style="outline: none; text-decoration: none; color: #20824B; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0;">
|
||||
<img src="https://res.cloudinary.com/cpress/image/upload/c_fill,g_auto,w_600,h_145/e_make_transparent/co_white,e_outline:7/vvpdctzacmq3xehpvwps.png" style="max-width: 95px; outline: none; height: auto; text-decoration: none; line-height: 100%; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0;" width="95" alt="Memetria">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@ -71,135 +71,175 @@
|
||||
</table>
|
||||
<table width="100%" cellpadding="0" cellspacing="0" bgcolor="#6ca629" border="0" style="border-collapse: collapse;"><tr style="max-height: 90px;" width="100%"><td style="width: 100%; font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0;"><img src="https://res.cloudinary.com/cpress/image/upload/v1653576619/lgfqinzbdqttwmhvljxb.png" alt="Node.js Weekly" width="100%" style="max-width: 100%; outline: none; height: auto; text-decoration: none; line-height: 100%; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0;"></td></tr></table>
|
||||
<table width="100%" class="el-fullwidthimage " cellpadding="0" cellspacing="0" style="border-collapse: collapse;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse;">
|
||||
<a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56r33X99p56c-2BoQkXyvZyCSjTZLSGaJeDgRqxp4BHT6TVg-3D-3DltCD_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oRZFTEd8tagj1xrExh63vc2fsMxtPBIvBloEnVsPDJDrHJade5bgD5Erq-2BohGpLWflXsRD6G1rKR4ZcrTC8NKlRIZS39NoNHuZi-2Fbc3kySv5bggDbcdEUA1rEfwqlUrKwQfsp3VWqQ9ryFuLkpH43zw-3D-3D" style="text-decoration: none; color: #20824B;"><img src="https://res.cloudinary.com/cpress/image/upload/w_1280,e_sharpen:60,q_auto/j5xkf1n4v2tmwakegtkq.jpg" alt="" width="640" style="outline: none; height: auto; text-decoration: none; max-width: 100%; line-height: 100%; width: 100%; border-bottom-color: #6ca629; border-bottom-style: solid; border-top-width: 0; border-right-width: 0; border-bottom-width: 3px; border-left-width: 0;"></a>
|
||||
<a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56ra-2BHbYUbZAgq0Awl4wQsazE1bhe-2BpCdYTFO-2BpNDWqk1g-3D-3Dx_-k_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEywLHI2112PJhYLaCD2-2B4Qi2ns-2B9maxytQrBvMSB-2B8MfIUORT1WVSjPTq-2Bh4G3A3lBW-2Farr-2BCgaLkASB8cs72Etj9NzjvjLjq0RIF-2BRJpD59rWnNLk7xaqY7ME5U1vFkpFBhhj0ekUSlb3782-2B9K-2F8A-3D-3D" style="text-decoration: none; color: #20824B;"><img src="https://res.cloudinary.com/cpress/image/upload/w_1280,e_sharpen:60,q_auto/btuiykgloamnvwq81bqh.jpg" alt="" width="640" style="outline: none; height: auto; text-decoration: none; max-width: 100%; line-height: 100%; width: 100%; border-bottom-color: #6ca629; border-bottom-style: solid; border-top-width: 0; border-right-width: 0; border-bottom-width: 3px; border-left-width: 0;"></a>
|
||||
</td></tr></table>
|
||||
<!-- normal content section -->
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="content el-content " style="color: #222; border-collapse: collapse;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;"><p style="text-align: center; font-weight: 500; font-size: 1.5em; line-height: 1.3em; margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56ra-2BHbYUbZAgq0Awl4wQsazE1bhe-2BpCdYTFO-2BpNDWqk1g-3D-3DlwD6_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiE0eL0BNqOCtCV6HNY9PPUOyevCTulgFpYrJLPMrODUpo9ZlnK1AD-2Bniu050zhRPUxXdQw09PH0Oa-2FMnEJ6SEksBeVLjWhroT-2FdcjDCYGYJI3JXjG7w6y5Y1P2aKWESeTweor-2BgP5OwCb8PiyEYnvY4A-3D-3D" style="text-decoration: underline; color: #20824B; font-weight: 600;">Node.js 19 Released</a></p></td></tr></table>
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="content el-md " style="border-collapse: collapse;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;">As an odd-numbered release, Node 19 will never become an 'active LTS' version, but sits as the 'current' release that gets all the tastiest new features until early 2023. It then reaches 'end of life' on June 1, 2023. <em>"If you’re interested in getting access to features early, Node.js 19 is ready,”</em> says Rafael Gonzaga of the core team.</p>
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;">New features this time around include:</p>
|
||||
<ul>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><strong style="font-weight: 600;">Watch mode.</strong> An experimental <code>--watch</code> <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56ruxEVXc6zdHvXDjQWO6GWV1hsJF2jnSDVCPPE-2B46-2BEXw-3D-3DGDsQ_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiE85sNToKZbhkQgdcYiNYy09pXE7Mss-2FT-2BWWmPTtE16FZDw-2BBxRWItDkkpGsOs0l85XA7Qp0gH-2Bt0qMBFSdiqHiiwWyPYk8tkl2t-2FxUvceWQ4yFDgDNYGjAHwkbjkPy4W5Dwi-2F8YtQ6t6CA7T24-2Bj2-2Fw-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Nodemon</a>-esque mode for 'watching' files and restarting the process when imported files change. <em>(<a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56o5GgJdUG7iJcRdGpnWZ0KvXQBk9obJNHL5RxWsre5iZA-3D-3DqTrl_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEpVnUiEbvkWa5gPeGUckbnl9bUC7BL2PhmnRo275gLDEvN-2FFEfGitBp9n7jRumgwOZAQXI29Up2JuJ2xhXWd5CQAYgr-2F6BF2YHBDEC6NQ1nXPj92WMk5Gg-2BsumDorduRpqNunGZ0-2FvoijqYWTY9i5fg-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Node 18.11.0 (LTS)</a> also gains this feature.)</em></p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><strong style="font-weight: 600;">HTTP KeepAlive is now enabled by default.</strong> It's always been an option but now it's set to <code>true</code> by default. The default duration is 5 seconds.</p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><strong style="font-weight: 600;">V8 10.7.</strong> Node bumps up to the latest version of the V8 engine. It's not a big jump but does introduce <code>Intl.NumberFormat</code>.</p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;">The WebCrypto API is now stable (with the exception of Ed25519, Ed448, X25519, and X448).</p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;">Some other dependency upgrades, such as to npm 8.19.2 and llhttp 8.1.0.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;">As things stand, we're in the odd position of Node 18.x and 19.x <em>both</em> being the 'Current' release, but Node 18 begins its role as an LTS release on October 25. More info in <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56oOd3d9g7syJCuuzhYGU5q0P3DGKSAer-2Flh-2BmEEnII5wA-3D-3DH0Dx_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEiHRRXVZ11Fq4nkMyyEbbC1wA2pRpHWhC4llcA-2BYJ6q9ueHZ017rEmrt3CV1OmltIU9mtUtBHaGAZR5jSE4aE69XdpM-2F0LdDnoHRUT8GnHy-2BfMNXad5w-2Br1ntIspk30NhtUmq4-2BSMewSushKjXWBdHQ-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600;">the release policies here</a> and the OpenJS Foundation <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qrMesfWVIK5SSGCZQ08d5nHLQmOP4ATLCQxUZOYB3ciw-3D-3D7mDZ_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiE9ONJiDUK-2FDTkiyXGqSRBferEuU50kXhjgqmiycgdeboszCUd5meSODSQD6i94wjUjxydF9vILLHutXJVOrX33LbaUEFZaDkM5ii-2BiUiqkJwoRTA7cN7fDMSrC-2BQDqJfHznVo0Bw4-2Bk1GVBbEuhARxw-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600;">has extra detail in its release post</a> too.</p>
|
||||
</td></tr></table>
|
||||
<!-- normal content section -->
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="content el-content " style="color: #222; border-collapse: collapse;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;"><p style="margin-top: 0; font-size: 0.8em; text-transform: uppercase; color: #999; margin-bottom: 0.8em;">The Node.js Team</p></td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
<a target="_blank" href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56r6zTNF2xDv1ApolVrZ4iZ0HiftFJvNFqLdyt1qEIYOmw-3D-3DRMCc_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiE41hCIBcXkIer6RlARsr61xFJRVEQg0uvdeFx4QkB9sayXkded6W4yvqCkph-2BCeOuA3AS9pg25IkcniP4slO9Ld-2B5D1RLxw95o1VkwLwniSFUyUA2-2F3VpcbAALDBF8GMNgK4X4-2FHyjD4gfRv7nrJP1g-3D-3D" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;"><img src="https://copm.s3.amazonaws.com/f6a5d26d.png" width="95" height="95" style="padding-top: 12px; padding-left: 12px; outline: none; height: auto; text-decoration: none; max-width: 100%; line-height: 100%; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0;" align="right" alt="" class="som"></a>
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56r6zTNF2xDv1ApolVrZ4iZ0HiftFJvNFqLdyt1qEIYOmw-3D-3DiAJ-_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEnTYwb0bfkKt-2BTsRdM05zg1psxx-2B0TUxf-2B5ReFuFSUxaQhVo1mr86cfdMKIPpA-2Bvj5TmeS5N-2By2FMfRISarHe8lYAp3iM-2F2pCCHU89FDlDIbdy8DTU85grvwXdcP0Zj-2BHCC9OH5f1xhfApbr-2BtvTu8A-3D-3D" title="dashboard.memetria.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important; font-size: 1.1em; line-height: 1.4em;">Memetria: Secure, Scalable, Full-Featured Redis 7 Hosting</a></span> — The latest Redis features, instrumented and scaled with the tools teams need as they grow.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Memetria <span style="text-transform: uppercase; margin-left: 4px; font-size: 0.9em; border-radius: 2px; background-color: #ff8; color: #997 !important; padding-top: 1px; padding-right: 4px; padding-bottom: 1px; padding-left: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #eeb; border-right-color: #eeb; border-bottom-color: #eeb; border-left-color: #eeb; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid;" class="tag-sponsor">sponsor</span></p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56r33X99p56c-2BoQkXyvZyCSjTZLSGaJeDgRqxp4BHT6TVg-3D-3D7AsA_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5ohDVd7ZsmGx0b8o3hOJp83xLWGawB5-2BDej6ckpFx9APA8duJGxBh6ha1Xyz34b30EfRIQWt1WNcfxVG60b6nVJUkao7vuf8CxGtkeJ8vcR0Yp-2FYbxCuxhmKl81SmcZrCTSNppRAt8xw1HSCgXv8RSbg-3D-3D" title="www.npmjs.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important; font-size: 1.1em; line-height: 1.4em;">njt: Quick Navigation to npm Package Resources</a></span> — Provides a rapid way to jump to various destinations related to npm packages (such as a project’s homepage, repo, issues, or even a package cost estimation). You can install it for use in your terminal, as a Chrome or Firefox search, via VS Code’s command palette (via <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56ryfaycpSzGGyqxNwqw9LCBSYTzJhiY5AB9bYedO1sl-2FQ-3D-3DBDcJ_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oIYoXE2ib3Xc4aHgoXzXzxx-2FaaHJex-2BWecilx3pK25Nq8XZfYCQn5inqyT2ThP8WIg6A3rkPTGrD8oA4kUqbNBuOJ1p6tke1Kl8Xz540OlpyrHbsxKHQAP6qiCau97XSOdvQk-2BLBBkGmR0Q0jwpkmzg-3D-3D" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">LaunchX</a>) or you can even <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56o9M1A10Mvfwp8mxNz3W1wgGS-2FnFRV6K4tM3fUDh9wLwg-3D-3DCLJ4_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oKcpCWa-2Fp7I5oop-2B-2FyxZKDNfETJ5f0wepxNValAMQqs3-2FFfm1ifhZ6Op7cPZ6AUohGvlZSvHpkyQ1OzwrnZRs5NLWnTppseUMrrWFtpHvLvDq-2FSunmkkUaHgMYmJbjQrWKfNH9fCrpTpuPM-2FdkG35dg-3D-3D" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">use it directly on the Web here</a>. – <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56oMXUrVHnshIFIB7xjjTm8CXRQXm7bIE0C0caYkMvui8g-3D-3DGgl1_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oN-2FZkABGU0huZ2ejRG8agESpJ8745DPTbjTRsDYPhUUtaqEyalQZ6cWlYshrN-2BIy0R41Q4aXWM3oZ-2FSCQW4eyvPFM8yQgLMD2CVMas5XqF6pvu276nRVrHvLZM9v7VEQsECxem4tT763QqXIHUWxAqg-3D-3D" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">GitHub repo</a>.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Alexander Kachkaev </p>
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56oiIcmdO2yLfzc-2B2dmuwutChcZrUvs-2FJsMh-2Fbx4RlOp-2Bg-3D-3DjC_V_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEMbvGDsLC0D1Uxd-2BHK5i6FxjF9-2BDW-2Bm1TOiyFLdO96D4amv1GgN10JVLdZm54hEwMmuudjjakVDPtd4Kfd3pHNl1Nfj1X0YVM-2FkHMmTzl0xGEmk0-2Fc23UENZS-2Fqa-2BYLvjCCfet68lrKA5Slwz-2BqnMQg-3D-3D" title="snyk.io" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Choosing the Best Node.js Docker Image</a></span> — If you feel tempted to just throw <code style="border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #44cc00; border-right-color: #44cc00; border-bottom-color: #44cc00; border-left-color: #44cc00; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; background-color: #fafffa;">FROM node</code> into your Dockerfile, think again – there are other options to consider.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Liran Tal (Snyk) </p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item video" style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink">▶ <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qEpyR0CkDGEzK0tRuGFlSvvWO8Ztem5Ty7OJokEMfauQ-3D-3DGt24_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiECvpY8GWhA5iH5KCmrSjup4rXJ3bXNCQEc61LrXRflOsQgMlzsU73Q6zIKHgsA33IN7O-2FOJVw-2Bt-2BqqguiMxNW096so9eUJ5V9VTD0QNiooeEItxwOhpaF-2F7kIrJp-2BQmv98wUVgdAFuoxruBYE-2FMJahA-3D-3D" title="www.youtube.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Effortless End-to-End Type-Safety with Phero</a></span> — A demonstration of <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56o7nEYk0ZLSUtFq-2BAYb91c-2B4dnOuqNDG5GMudFLW-2FUDrw-3D-3Dd4VO_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEORUVm-2BZJ2XcN22VonQLtBmuAWao9OZYseUY20aANHVf8CDV3rrpRp9Eqh7hgq3klG3d5QoPMoJi1lHWlqqowV6TXKksTN9N9U4gT4hAcRUwDAs107tUxsi2vSTin7TPPK2rAr8NdN-2FX9WWEU8TYD3g-3D-3D" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">a library</a> providing a type-safe TypeScript-based way to communicate between frontend and backend. <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56pu57-2FqlCUJj39kXRQgxghrMPmQcqzfjuqdd6mUvMolwA-3D-3DmCHK_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEErCjJ0vDOOc1JpHffSWIUcUkQ0eEvhX9b9dA9cmmA6SMlrbIfNFdBhOrZKijIOLjV62WLI1hkD9SxdPm5kXKxHZURN-2F0wbYkYUuHnGb7k0fuAwEBCj5lhWmPvk0TOMketN0VM5m1o-2FIuA4aNSTkxGQ-3D-3D" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">GitHub repo</a>.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Jasper Haggenburg </p>
|
||||
</td></tr></table>
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="content el-md " style="border-collapse: collapse;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><strong style="font-weight: 600;">IN BRIEF:</strong></p>
|
||||
<ul>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56o5GgJdUG7iJcRdGpnWZ0KvXQBk9obJNHL5RxWsre5iZA-3D-3DXRY7_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEwIwBXpMOErZx-2FqGnNqcQecfKHlhtTIqomF-2FePIShGjHReIDdWcAkCJ6nwLET7n1OZItRIpVN9UKvnmQ5nSahyFl3UHLyX5b-2BaOhkrNypLnq45FWXeCC2C6zSd7J-2FLZTQH91JgT0KaY9ZKKJWsWW7zw-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Node 18.11.0 (Current)</a> was released last week. It shares Node 19's new <code>--watch</code> feature and Node 18 will become an active LTS release <em>next week.</em></p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;">The OpenJS Foundation has notified us that <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qUV-2BSh1TLqu4nUC47bRFmODv9-2F8ge44Nxnet2bo-2B9vCQ-3D-3Dxc2B_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEMK0qbk8DOZO0rg-2Fn70aUcETXWQawfUrJRDUa-2FG-2BJh6-2FQ8HHBRPcaX3AHpFhlqf07eaxDpaoeTwzl0Fe5krdfkPsO0RgVCHDEueTASGaM4ZPuIhjM-2B6mCvYm8gRLigIGWdS8hiEZHtj9-2FsAYHKPviag-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">there's a big discount on two Node.js courses and certifications</a> until October 25.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56rvexAd1BFzEQ1Z1K-2FR52lz8ve-2BY3LZbSRsOH6g7Eb6lg-3D-3DfXKx_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oKXxy2YoTpvcndoOelA5icQgneaalcTPkrJT1Qw9-2FjNOpZWevQ0ZXSkQCXdp-2BWyQlX5LtU6OP-2FNBsW7cw76vdP8T9bN850y1-2FgHhjRqqpuEhN0MDj85sVzdtX-2FBdfyyyHJzVc5WuI96wyHSROts3a1g-3D-3D" title="github.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Knip: Find Unused Files, Dependencies and Exports in TypeScript Projects</a></span> — Knip’s creator tells us it’s Dutch for <em>“cut”</em> which is quite appropriate as it’s a new tool for trimming away things that aren’t being used in your project. If you just want to compare it to similar existing tools, there’s <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56oszfxENsl48ofro0lCRJPWD789NPruHA1zcfvOG5m-2FnQ-3D-3DI-tJ_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oFcG2yzQzPp-2Fu6HGH5MceESqDQjFfOG1hL2w144Vayi06RSqqXGhIO4XOtRRjO3-2BU0n3UUkKVVIqXDmvd6aqh0B4Y04rYR-2F3ozmFjoDLSAZzHRe0leu-2Fcwq8TOVsSXB5Vj6Y5MjU7yPWTF1cmW3cu8g-3D-3D" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">a handy comparison chart</a>.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Lars Kappert </p>
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56pgbt-2FySMq6TE09iMZu2f31rvDqLcToe-2F30wzttQjUAzA-3D-3DBjPi_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiE7W2Dr5r4L3sT7m5tNPcmGBoMgsI3-2FKxQEmXnfN2eC3AZyuxc9rY3cQvwR3JALkgz9uSi-2Bd-2FhPUlDFIq387uc2dQbrYlm4CLRbnNPzSE-2BcghrotWXVBAdtEVoie99d3Ea2omPTXNoSBsH-2BwYr8Qm1lQ-3D-3D" title="www.lloydatkinson.net" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">PowerShell, NPM Scripts, and Silently Dropped Arguments</a></span> — If you’re a Powershell user and you’re finding that some arguments aren’t being passed to your Node scripts run through <code style="border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #44cc00; border-right-color: #44cc00; border-bottom-color: #44cc00; border-left-color: #44cc00; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; background-color: #fafffa;">npm run</code>, Lloyd explains what’s going on.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Lloyd Atkinson </p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
<a target="_blank" href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56o-2FofL8qV45mZXO-2Bx2UGhMR-2BEL2eksQgpS5LzPvvH6WGg-3D-3DRmzT_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5onIxQQMnyVZK5WzSPovxxvKWOCx8u0rtr-2BWaHng3PMaHaSYLyQVYdsqkI4RBMCdOi6RqI6Q7kOWPfoRUzA1GwQVASZWRceAYg7wQUsnQ-2FugfVupslmbvQN3TeYXDC30UFOvmEJZoTcONsinRwKKKWXw-3D-3D" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;"><img src="https://res.cloudinary.com/cpress/image/upload/c_fill,g_auto,w_200,h_150/ulhdzgena0zcgszxdsks.png" width="110" height="110" style="padding-top: 12px; padding-left: 12px; outline: none; height: auto; text-decoration: none; max-width: 100%; line-height: 100%; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0;" align="right" alt="" class="som"></a>
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56o-2FofL8qV45mZXO-2Bx2UGhMR-2BEL2eksQgpS5LzPvvH6WGg-3D-3DbGbd_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oPqRUCCh2651yeMUrVWdPm7HNTb-2FJ0yE89KPgSfsothIbHldh8u7XE5dxw2MENAS5jBFmzPU60sQoMvKxtpi1CeGRK-2FNCE2AXdc0PP9M5ar3pYy7lMvYokZnvps9JOzQ-2FhMgwd-2Bpamb-2BT-2FvAktl8yzw-3D-3D" title="userfront.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Node Authentication, Simplified</a></span> — In this article, we lay out a new approach to authentication (plus access control & SSO) in Node.js applications.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Userfront <span style="text-transform: uppercase; margin-left: 4px; font-size: 0.9em; border-radius: 2px; background-color: #ff8; color: #997 !important; padding-top: 1px; padding-right: 4px; padding-bottom: 1px; padding-left: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #eeb; border-right-color: #eeb; border-bottom-color: #eeb; border-left-color: #eeb; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid;" class="tag-sponsor">sponsor</span></p>
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item video" style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink">▶ <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56r8HVF8il4M7AdNF0iaS22Hww2wbq5ARCcyx3e8SMxYQA-3D-3DEM8X_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEBtqmX6njGwwn4fsBv5dCE6cKsTlCIxFUhw5oKxZGMrNPRwb4mMR5KJMNVPYqt-2BZKeWHrKAGIObaPPga1hxZPWwiGNghddutMyGqNdHxGq3QWRO1DlnDz8R-2BfX6R94odYC4bi7BcZvpA5VCmP25Yuww-3D-3D" title="www.youtube.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">A Next.js Crash Course</a></span> — There are a lot of such videos, but this is a well recorded and up to date one so it might help you get the lay of the Next.js land if you’re just starting out with it. <em>(2 hours 30 minutes)</em></p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Anson Foong </p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56oChoowk0RSpGq8L5EUdqg6Mk4ViCMqSTPsZZQ6eJXVpQ-3D-3D4x9d_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oHUKdeIRAXLyZqA25thjsTkUNg6esSCEGjKVwkgVOdNN7-2Fw-2BDJM2ghkEwfk-2BPet-2FzNjUC-2FNmG-2Fp2m47h1aHdtvPg7jvPeif6kpM2ABVI44MFutnhnBik-2FMYV-2BN4OtMl1lAoZCaGUDJtUnXb-2Bxmv5AUw-3D-3D" title="nodejs.org" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Node v16.18.0 (LTS) Released</a></span> — Largely backported fixes and tweaks – no big headlines here.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Juan José (Node Core Team) </p>
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56pJ8YlJIJ9WvtJBwvcosmZf31RLtinTKHpBKyBhSUvorQ-3D-3D59Oa_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEi9roa4mmLsgNtqOzeNn01J1YAbtCNH-2B8aloOjPK88QUP7vc4LZx1D8-2B-2FB5yK6nNGPtm0UNeY5OCRmaCPZZz4DJQ3FZOMx0PT6NkCjvx5JGa7EvcYdYvbrIW3nSigx3-2FaNVARy9iDf0LSdGd4Y89Tmw-3D-3D" title="serpdog.io" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Web Scraping Google Maps with Puppeteer</a></span> — We’d be surprised if you’d get away with this for long given there’s an official API, but it’s always interesting to see how it’s done.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Darshan Khandelwal </p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56pyRq52wBhP8m2828RL4kN1h65-2F6OQ-2BCbUMzAgjjafJ1A-3D-3Dj_so_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oqa3o5N6MIZwD68yuI08uap8M81kUq76W-2F-2BRput-2BAGuej6fOLCznj1iYSGms9eBmOH4qc1taMGo-2F9XvqXYQjKDfmhuzZ-2FKoLJyd8xKSK1SYmIVfgusZYkU4CK3-2BDJrCa3GbOWHN91GbgJCTJMfIDJ6w-3D-3D" title="2ality.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">How to Write CommonJS Exports That Can Be Name-Imported from ESM</a></span> — If you’ve ever got tangled up between using CommonJS and ES modules (I sure have!) Dr. Axel clears up a key cross-compatibility concern here.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Dr. Axel Rauschmayer </p>
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56oZg-2FkiLgU2V8f4woEYibxJHD8uLrNzPXOs1Ag1vo6JFQ-3D-3DzHHQ_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEb4ODrRNEvsB4u6ffP-2BaP1XqgSFWAga6Slj8yjWtDlzkdrHRHZWYvQB4jtY1dirZvLRoO5bOBJWU-2FOYF-2BVRp9bQLRSzvFYzsJa-2FyZmh7NbOAwC5USrjB2dD9bW53LEQ-2BCNBjeqKZYeIW6OC4EbAU2wQ-3D-3D" title="snyk.io" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Your Step by Step Guide to Containerizing Node.js Web Applications</a></span></p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Snyk <span style="text-transform: uppercase; margin-left: 4px; font-size: 0.9em; border-radius: 2px; background-color: #ff8; color: #997 !important; padding-top: 1px; padding-right: 4px; padding-bottom: 1px; padding-left: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #eeb; border-right-color: #eeb; border-bottom-color: #eeb; border-left-color: #eeb; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid;" class="tag-sponsor">sponsor</span></p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56oQbdtlpnISQqfDvc3VKWuTdeYDqgTkrAjd63cGYt8oRA-3D-3DXc0V_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oKXaoDnQFCD8-2Bqr-2FQF2CB4HVAynqEbso6njSdNpJKRjdvCpTZ0te3pVHP5KPhqLTGpUTjQnlVVlpt08QFsDzVaLigsfIMKSAUquq97I3Mwj5qxPjU2ZFVa2gdAL9Xm3ST-2FTSHFf8ZHeS5MTPAZ0jhxQ-3D-3D" title="sprkl.dev" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Adding Observability to Jest Tests</a></span> — A look at how to get a bit more out of your Jest-based testing by keeping an eye on things.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Eliran Maman (Sprkl) </p>
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="miniitem item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
<p class="desc" style="color: #5a5a5a; line-height: 1.5em !important; font-size: 0.9em !important; margin-top: 8px; margin-right: 0px; margin-bottom: 6px; margin-left: 0px;"><span style="font-weight: 600; font-size: 1.0em; color: #000;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56pbGJPd9-2Fk9QMCO9UqoTzlbeOrMrbj6gcPiBzVy3BuW8g-3D-3DMHs5_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEQY9mKcMppAe8QFvMPKT3WKSEU7aO7GXRWkrX4UTIPKvaP7t30qqjsvx7Tj6dz5MV5BDR1m9IjyX0LYtNjEqGMZmomHOfZi0Jn2joYlUro7UkBlPBC-2BChB1aYflkjYpZcmbHbjzL2jJP3ar9ds38xLw-3D-3D" style="text-decoration: none; color: #20824B; font-size: 1.2em !important; font-weight: 400; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Sending UDP Messages without DNS Lookups</a></span>
|
||||
<br><span class="name" style="color: #bbbbbb !important; margin-top: 4px; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Herman J. Radtke III</span>
|
||||
</p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><span class="pretitle">🔐 </span> <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56pgBLkiT1NIC9WT7QzIrXzrGWc0wlDwjmnxqTDin9LOLQ-3D-3DF7HQ_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oRI6p9q8LJzKYWg1WtuXUy83FLHi31XbhQN5ICNtwx3s18PY-2F5a56VvP7KQg7SuUoNA4l0zWz4WPyIfUimxVsVKpMF5SoCyPCg4NN-2FVSZHG-2BaErc7wAwFHZGhTsRCxfhOvwFwxQDNCJjZd-2BHSyfah8Q-3D-3D" title="www.smashingmagazine.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Node.js Authentication with Twilio Verify</a></span> — If you’re happy using a third party service, bringing two-factor auth into your Express.js app needn’t be too hard. The author demonstrates the creation of a simple app that authenticates users using password-based authentication with an extra layer of OTPs (One-Time Passcodes) powered by Twilio’s <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56pPv6N0F1YQBOwPPrX9Mh7VUUH5v2GYk0G4-2Fc-2BaxXRThQ-3D-3DbSTw_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oTZ092PLn-2Bfi49blEisJR4kQ-2BQmsoB-2FLQYPQc-2BlbxYfRxBcoyB0bLQd6orLXc1pB-2FoNjwZL5Dy7Q3dFeu-2BWXM4eK7Gf3keU5oZcr89p9U1mS43n7Jz3397emcJr6fgFb1TyCW2utsEL7uDx8nJOab0g-3D-3D" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;"><em>Verify</em></a> service.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Alexander Godwin </p>
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="miniitem item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
<p class="desc" style="color: #5a5a5a; line-height: 1.5em !important; font-size: 0.9em !important; margin-top: 8px; margin-right: 0px; margin-bottom: 6px; margin-left: 0px;"><span style="font-weight: 600; font-size: 1.0em; color: #000;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qnkx7zCeqBic9p68wBkQfUE-2BzMKZCr0iiPuvv3WyCOuw-3D-3Dz1E7_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEQTNbbCohlDVOQmzdJrngdW81lDdWUUXzVPWff4zPdFL7O2WTlvJ-2BHBW1Q0OLzA-2Bai-2B8wLqjgbdqMwAEvbr6PmYGGX80JegH-2Fl5kh-2FI44f-2BIkEc56lCLRw88HBpyJ3BGUtbWvKJK0263ue2bv8m28hg-3D-3D" style="text-decoration: none; color: #20824B; font-size: 1.2em !important; font-weight: 400; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">How Wix Uses Threading in Node Apps to Cut Kubernetes Pod Costs</a></span>
|
||||
<br><span class="name" style="color: #bbbbbb !important; margin-top: 4px; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Jessica Wachtel (The New Stack)</span>
|
||||
</p>
|
||||
</td></tr></table>
|
||||
<table width="100%" cellpadding="0" cellspacing="0" style="border-collapse: collapse;"><tr><td style="height: 6px; font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse;"></td></tr></table>
|
||||
<!-- normal content section -->
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="content el-content " style="color: #222; border-collapse: collapse;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;"><p style="color: #46483d; font-size: 1.4em; margin-top: 14px; font-weight: 600; border-bottom-width: 4px; border-bottom-color: #eeeeee; border-bottom-style: solid; line-height: 1.4em; display: inline-block; margin-bottom: 10px;">🛠 Code & Tools</p></td></tr></table>
|
||||
<table width="100%" class="el-fullwidthimage bordered" cellpadding="0" cellspacing="0" style="border-collapse: collapse;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse;">
|
||||
<a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56rvuMP536gYURAk5hBAdy93PhjBcB1VORZKEegDBbPaPg-3D-3D6DlY_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5ock6Z9kNalLVkAp66V4a1CiqvjlQmsH2STN3jxbx8QMI-2BEgVtAB3RQIgbAMUZvJ-2BepV3H3enxUr74Ygi14HpiCHV-2BMsrUGLP-2FM5OO-2BLCtOm0PnP4sKWQof2KYfEDKhWvEYNkTtXsACZ3-2BRVq4VAEGtA-3D-3D" style="text-decoration: none; color: #20824B;"><img src="https://res.cloudinary.com/cpress/image/upload/w_1280,e_sharpen:60,q_auto/zlg7sxinigfuwzhxvrzt.jpg" alt="" width="640" style="outline: none; height: auto; text-decoration: none; max-width: 100%; line-height: 100%; width: 100%; border-top-color: #ddd; border-top-style: solid; border-bottom-color: #ddd; border-bottom-style: solid; border-top-width: 3px; border-right-width: 0; border-bottom-width: 3px; border-left-width: 0;"></a>
|
||||
<table width="100%" class="el-fullwidthimage " cellpadding="0" cellspacing="0" style="border-collapse: collapse;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse;">
|
||||
<a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56obUL9N28GQk2jDIabY38rWiGYPofllyLLFcoRk-2B6PyWw-3D-3DZwDA_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEMxB1Ex0Rb9NunayuZXgdiOXJ5q77sbWlJ-2F0LBVwVIwuKxKtNmoRQYO7JObxlRKuFP1wX0FK1s4QJhigO7-2BmaWj58uTiGF1Tc4FtQ8n9QBEippmidDWfpRJGpPoK0yVl4Q2absvQjm7l5xhGvO2qSPQ-3D-3D" style="text-decoration: none; color: #20824B;"><img src="https://res.cloudinary.com/cpress/image/upload/w_1280,e_sharpen:60,q_auto/ny0bnuedwfudc7fhqojv.jpg" alt="" width="640" style="border-top-color: #dddddd; border-top-style: solid; border-bottom-color: #dddddd; border-bottom-style: solid; outline: none; height: auto; text-decoration: none; max-width: 100%; line-height: 100%; width: 100%; border-top-width: 3px; border-right-width: 0; border-bottom-width: 3px; border-left-width: 0;"></a>
|
||||
</td></tr></table>
|
||||
<table width="100%" cellpadding="0" cellspacing="0" style="border-collapse: collapse;"><tr><td style="height: 2px; font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse;"></td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56obUL9N28GQk2jDIabY38rWiGYPofllyLLFcoRk-2B6PyWw-3D-3DVv04_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEYJooQOIMS3B1eG259-2BgO711KOnAMlYa4vQ-2BFjil81wOKdBTc-2Bpy5XEmhlSm2qnFiqILBkZwp77Yq-2BJnHdRKzQwQQHUU0WAsYg2fdPMhFz1fSto5-2FclJqiiL-2Fii4J-2FEiXuq0A-2BQfOQP9HvuXI9KUgaw-3D-3D" title="www.caoccao.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Javet 2.0.0: Embed Node and V8 in Java Apps</a></span> — Lets you spin up V8 interpreters or full Node.js runtimes within JVM-based apps. There’s <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qZBRT-2FC8gRDWONKGBZP-2FrlOzhcUwLUeh60If-2Fad1MFaQ-3D-3Dpuu8_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEmjagHflkwe3kz5g7rZVtxY-2Bsq8pKK60-2BhYFt-2FTKjJA-2Br0ujFC2ySkSjtyQODkd3NJxOEJ07XfGIe-2BDRSStsKnl7a54dJfIZnoLKEvyLv8uyEoDd5XBKVpCSznYme31Q-2BW2IEDUCiybcDFjAGtPsmYQ-3D-3D" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">a slide presentation</a> to sell you on the idea and demonstrate how the integration works. <em>(The name Javet comes from Java, V, and Eight.)</em></p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Sam Cao </p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56rvuMP536gYURAk5hBAdy93PhjBcB1VORZKEegDBbPaPg-3D-3DoHDU_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oWlgpwOEEW4WmEIuRbDt2zP6adIbWzMFCSqkcEUE-2B1WeXRc7Gj-2FZjqeprxYayd7Nl-2BL2XQ4WmWCorC-2FnMQmvpgGYzLEU1JFrjCamfFdfstlQ-2BrlO098dgufhnDKnLMeBkJ3MlHc2NRx-2B81LnYUmvLHg-3D-3D" title="github.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">IP Index: A Fast IP Lookup Web Service + Library</a></span> — Returns blacklist status, detects VPN/hosting and shows geo and ASN info. The repo gets updated every day too.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Mykhailo Gorianskyi </p>
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56pmi-2Foyxl43aHHHBd8Ih7RZN0-2FFTRrhuA2A2W-2BW4nCe2w-3D-3DaqiY_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEaOinXu-2B4F8eHBhAJ1pAxJmXAdeQJYH6dSqx39Rkgb6xv3uD06e7MQXFuPzjBKRySIAd08x9nmzuPI2po-2B6K-2BggdtQAbL0Gq9-2F4CMnlAhiDRxk-2FrnQe7D9bRTNTwj8llKlbzXk380RUsAtPkI5-2FIyaA-3D-3D" title="github.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Editly 0.14.0: Declarative Command Line Video Editing</a></span> — Brings Node and FFmpeg together to let you more programatically edit and construct videos instead of wrangling with arcane <code style="border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #44cc00; border-right-color: #44cc00; border-bottom-color: #44cc00; border-left-color: #44cc00; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; background-color: #fafffa;">ffmpeg</code> command line options.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Mikael Finstad </p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56q-2BfZ1GvwT33-2BQ8qcVXwdKW843y5BQS3uOp1xZDnZmBkw-3D-3DUc0Z_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5o9ooLqPGAJJJkww-2F-2FdvKTd96xGkgG0oVRBz-2FEkwvaF5YBu-2B1iQpG4Vz6savjBm46yxbL2fMe2xKYLr0433HhiF9-2Bjnhz08nSnC5lXIVG-2BzklZbcOcCC1Pbp7q4ExquJ-2FLRmpVBiywVcxqkkXQnjTqiA-3D-3D" title="github.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">cRonstrue: Library to Convert <code style='font-family: menlo, monaco, "Ubuntu Mono", courier, monospace; font-weight: normal; background-color: inherit;'>cron</code> Expressions into Human Readable Form</a></span> — Love the project name! The idea is given something like <code style="background-color: #ccffdd;">*/10 * * * *</code>, it will return <em>“Every 10 minutes”</em>. No dependencies.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Brady Holt </p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56rLQZ-2BI5zZa92e0TN-2FsTqqHAfh-2B5Z2-2Fbf5DRdgf8yrCrg-3D-3DFPJN_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5o3uINBtfW-2FaTywOjX-2FOoHgTty7fQyN6ReWC1JnhVY25DgPXSWGjsl97rfhHZ7WfjkLuq4xofhc7bhgN2mTcUzI-2FWCsBYOhom3OEejAokgKDh1gbYbnjnKSU3YOgq3LtxakzPeXtfBN2QRuZHQ0ipBOw-3D-3D" title="dynaboard.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Dynaboard: The Pro-Code Web App Builder Made for Developers</a></span> — Build high performance public and private web apps in a collaborative — code forward — WYSIWYG environment.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Dynaboard <span style="text-transform: uppercase; margin-left: 4px; font-size: 0.9em; border-radius: 2px; background-color: #ff8; color: #997 !important; padding-top: 1px; padding-right: 4px; padding-bottom: 1px; padding-left: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #eeb; border-right-color: #eeb; border-bottom-color: #eeb; border-left-color: #eeb; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid;" class="tag-sponsor">sponsor</span></p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qSvh5qzoTMqc-2BYnXNItQqUgKX3O8gyjTd-2B-2F4eKkrbomg-3D-3D3aNI_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oRf-2BxxHUlhfPo-2BD8RhsTAuaCB0yErxbU3B41gV1zfU-2BBj3WzE6LOdwav9Jes6VEncNHiSY3L3-2FaL5Q9kqpoWeDtrR8YlOcFBiGtNK2AUNy6oaJrhc11lJ9KOSrx2UpgvoEBfwAioHW8KOeGl9WsyxEg-3D-3D" title="www.npmjs.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Whoiser: A WHOIS Client for Node.js</a></span> — Given a domain name, TLD, or IP address, it queries online WHOIS databases for info.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Andrei Igna </p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56oX6ffANCPMl-2ByPsHSd2ObTf77eZoaigvCMyQ-2FjutCFVg-3D-3Dfpd4_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5o2PG3fdNak-2BKPGTUVxG8f-2BvXKB4me6HfLbLv-2BHGdXvFHNLU9pLYrxFkkXwY-2B50OUbmD-2BnIrBrY-2BS6QUy2gHq4rsO4r1E35T6kyiDwQtnTo3A3LHVSU1ER8pZw-2Faj2hB2th2k4BXaUPES5gLF0ZbQ0vw-3D-3D" title="github.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Print Ready: A JS-Powered CLI for Converting HTML Into PDFs</a></span> — Uses Paged.js to render your HTML file inside Puppeteer, then exports a PDF from Puppeteer.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Nicholas C. Zakas </p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qxonv79y6MSr0zLBknj4euMWnaBuhgxyAFMmhl3ITr1g-3D-3DmRPd_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oJ2smhmElNVw9VQRqDYtgZnMFNsdHfG11cusZRNZAkDMsvnjDPceN-2BcxG94gcHBTIPCFjgvwhtnjEMENfDhvG9E63UpHT1SFTsxiSA8rc-2BfU9RGe-2FiYNhg6NwLxdDFYNEjbvu4MrRyQartvyf8o30sA-3D-3D" title="github.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Check HTML Links: A Fast Checker for Broken Links/References in HTML</a></span> — An npm package you can run on static pages to find broken links in <code style="background-color: #ccffdd;">href</code>, <code style="background-color: #ccffdd;">src</code>, and <code style="background-color: #ccffdd;">srcset</code>, and can process 500-1000 documents in seconds.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Modern Web </p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56oylnjKqNii6FdEnIOwDwb8c4zkj-2FED5pK1iyg-2BhRbMfw-3D-3D7FuN_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5ozRjhvXRg2LCuRXgall08dDtDPnqleiM-2FS-2FBtF6VEcIHZ9sAVHUrK68pN0i1f09dunv3cTTwpEh26h2Mp7K7HLTmDOIGrZ85KFWqcLNSOswoBkz0ZB86U5GtGHjPSqhUg8iMV1NeBWBLiLAxQJzpO-2FQ-3D-3D" title="github.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">human-signals: Human-Friendly Process Signal Info</a></span> — Basically a JavaScript object that contains info about the various POSIX signals (<code style="background-color: #ccffdd;">SIGHUP</code>, <code style="background-color: #ccffdd;">SIGINT</code>, et al.)</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">ehmicky </p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="el-item item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56ph0IHShU2DSNTwQYgcZpn91uT96SyUpoHk36iRgGKlzg-3D-3D8Fq0_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5orXT9ztNVFO610ZQ1X-2BimoI9GKfKFty-2BcD7RLcFSDqtOP0J47Y8O3LpJ3VU-2Bd3-2Ba35BMhH49-2BOJB9UJXmEczgjouJW2i5NUxoshXzjwLJIPJxCNUY3lQDEN2xskOTmfiTHhzhYqBESMklD7L-2BMr2T-2BQ-3D-3D" title="" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Need to Upgrade Your Node.js App? Hire Us to Do It for You</a></span></p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">UpgradeJS․com - The JS Upgrade Service by OmbuLabs <span style="text-transform: uppercase; margin-left: 4px; font-size: 0.9em; border-radius: 2px; background-color: #ff8; color: #997 !important; padding-top: 1px; padding-right: 4px; padding-bottom: 1px; padding-left: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #eeb; border-right-color: #eeb; border-bottom-color: #eeb; border-left-color: #eeb; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid;" class="tag-sponsor">sponsor</span></p>
|
||||
<p class="desc" style="color: #222; margin-top: 0.8em; margin-bottom: 0; line-height: 1.6em !important; font-size: 15px !important;"><span style="font-weight: 500 !important; font-size: 18px !important; color: #000;" class="mainlink"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qDmTAnhDeqHG5g4bhdOnOl-2Br9ql0hDRnWc0zkvjvOBag-3D-3DFzJy_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEwFgMBPol2y4XWfrJGPDuKTB8sPjlanyrhwLnjzAq3uUm2XqJGoJ05wcauSDf9VM1xOqCY4kQSrepo0APylG1GdmOU-2FCBrymMr4HFU-2F0YIQ-2FdogieX3DdViTGMEDWRaCPbN3dru9lEPA7GvF6d4CNKA-3D-3D" title="www.courier.com" style="text-decoration: none; color: #20824B; border-bottom-width: 1px !important; border-bottom-color: #ddd !important; border-bottom-style: solid !important;">Send Email, Push and SMS with Smart Routing, with Just 8 Lines of Code</a></span> — Are you stuck using marketing tools like salesforce to contact your users? Send notifications from right within your application using the Courier API.</p>
|
||||
<p class="name" style="color: #aaa !important; margin-top: 4px; margin-bottom: 0.8em; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Courier.com <span style="text-transform: uppercase; margin-left: 4px; font-size: 0.9em; border-radius: 2px; background-color: #ff8; color: #997 !important; padding-top: 1px; padding-right: 4px; padding-bottom: 1px; padding-left: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #eeb; border-right-color: #eeb; border-bottom-color: #eeb; border-left-color: #eeb; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid;" class="tag-sponsor">sponsor</span></p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="miniitem item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
<p class="desc" style="color: #5a5a5a; line-height: 1.5em !important; font-size: 0.9em !important; margin-top: 8px; margin-right: 0px; margin-bottom: 6px; margin-left: 0px;"><span style="font-weight: 600; font-size: 1.0em; color: #000;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56pp4QEugKjvWTbqk0Cfq19OQAo5WgHRaHg3o8UCf-2BRZDA-3D-3D7hlf_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5okvg635TjdeFknmlXnaZ-2B1VK13pt219yrdzSdPMbQxoW-2FDD3oEqn3walUMBFA2VKymH3-2BiQu7urLE-2FKhcNDg7x-2Fk1I5x7iqCgVGh5TauZlf4HO9id0WOmdKwDUKX5NnE8mS9M-2F9lCfehUPkSL8lyLIg-3D-3D" style="text-decoration: none; color: #20824B; font-size: 1.2em !important; font-weight: 400; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Flyweight: A Brand New ORM for SQLite</a></span> — Early days but provides some extra abstraction around SQLite you might appreciate.
|
||||
<br><span class="name" style="color: #bbbbbb !important; margin-top: 4px; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Andrew Jones</span>
|
||||
<p class="desc" style="color: #5a5a5a; line-height: 1.5em !important; font-size: 0.9em !important; margin-top: 8px; margin-right: 0px; margin-bottom: 6px; margin-left: 0px;"><span style="font-weight: 600; font-size: 1.0em; color: #000;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56oi4WBOWKYkFSHAV9UWnU66V2qF9pwTUxOY-2BtVkmsVhqw-3D-3DQqbG_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEmcF7sRkm-2FtgysFoOOaCMx7ERrB-2FV-2BU9kXphPEkd5FzKU0XWQBCaJ3oPGFJnxLnlywOr-2BAjLFHmoGpmwjOQgV5tSMzfn4k46mR4q8h3VbgkqSu5-2B9xfKf1-2BzkRu-2B7NPLVHMb1y-2FzDWwGxXVAz6XbEjg-3D-3D" style="text-decoration: none; color: #20824B; font-size: 1.2em !important; font-weight: 400; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">lady-gg: Simple TypeScript gRPC Client</a></span>
|
||||
<br><span class="name" style="color: #bbbbbb !important; margin-top: 4px; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Mish Ushakov</span>
|
||||
</p>
|
||||
</td></tr></table>
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="content el-md flat" style="border-collapse: collapse; color: #444;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="content el-md flat" style="border-collapse: collapse;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
<ul style="padding-left: 0; margin-left: 0px; list-style-type: none; list-style-position: inside;">
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 6px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56pIo-2FFCC-2FiB5-2BX2-2BCWeioxIOaJaosm1IX0Ge5XmvvW0ww-3D-3DvUMY_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oTLMhJWFBjK3vsozafN5b7CBC-2FkWoZiQ6YrAjQHGWukUun5Z2hwgct8MbU7AaPCgvzsqO9H1gGVVgRJiGXHs1GEcyICer1M5H2UpQephQWN8qlIk34HPgC-2Bd416ae0-2FGcI3uq7ZGYE4lEYpY8RJvG-2Bg-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">AdminJS 6.4</a><br>
|
||||
↳ Admin panel / UI for Node apps.</p>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qOeR8dkPkAQ0Jc3M1LXMsC2n-2B4DdaMaRDxoanihfYO4Q-3D-3DlftC_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEHpVuV0GjA3o-2BrwQOX0yXSY3B5t4FT9Hc3pZG70HAX-2BIVsZwXerWCC7PBmaQEbu-2FnK9MczZAUIomrs50pGNGJkpiQ233VQn1njoXpwSh3W9Dd-2BnVr4l8cVJLI9Yf9FRcQq5YhDrHkNmBLtUka9LlxzQ-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Awilix 8.0</a><br>
|
||||
↳ Inversion of Control (IoC) container for Node.</p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 6px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56rI8YF1LXsBTzw9jwMDJAmOnyT-2F3ZRlqOl4loK-2F98XqDw-3D-3DFD2e_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5objuMpHQoBW8R6OWNxx7A4Qn2umv7MsiARYQ7tNxw-2FHRz3FoPgksw2If5WNHv926c2nSDnpkS-2F6YeVKa4xo55KoyYmziWEKcLxk2ukuw07d7vYOuYGpLgmGzJJr9O-2Fs7wtur8TJRpVX-2FUztD3zmEVmA-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Faker 7.6</a><br>
|
||||
↳ Generate large amounts of fake data.</p>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56rvyEVtR04BspjpessX7NIiAFfQ-2FNALchpdiWJ9GoGxPg-3D-3DAzJx_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEEGs-2FbNKfalgc1llqVE3T47xA8AMsJvDfWz8SHuluBer7ZwbLAnGKohGXwU4EqODaDd9gBUEiuInU8o2JJLg8jyCoSPsqdoo-2Bo3IS-2FYjaJFNq84QO33QKs-2Bm9ojOMUeB40b0HjTrK0V8UHLlSvzKiBA-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Nx 15.0</a><br>
|
||||
↳ Smart, fast and extensible build system.</p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 6px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56quhRPkiPRzNVsD9pPYa1pNb2pAgmF6ogOK73xxiDY57A-3D-3DNEq1_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oT1AbhYQrEGvX2nGXT804It8hYbkV9MbU4tMlyrGN9j7JDOsj-2B7TTJ-2FD1JcwkfQwQCerALy0jKwwNt0G3TgrAtkYrJa8np5NbVOSbW6djZHNiCh47XPoBihfwIvutt2kAW623N5PhfZDAcoq4hce-2FjQ-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Middy 3.6</a><br>
|
||||
↳ Node middleware engine for AWS Lambda.</p>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56rf0Y-2FoqotQ2mSPow42EISzYgNxsQXct6G8q7K8DEHQPA-3D-3DRgnU_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiERFHUm1paIHDjg5a7FnrOZZjbGb7mCWra1LOKrLsF6FvXb0h-2BnY7PAHXfSKeURuF7QxPIbufWEEZHSbmnUTK8mmrIcQP6VAksbqED6gED426rmi-2F-2Bq5K9pfnc2XzGDzRJ4DeVx4g-2BBw9HfBlsLO14bA-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Nightwatch 2.4</a><br>
|
||||
↳ End-to-end testing framework, now with improved component testing support.</p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 6px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56rkHLb0qtYqZ0Bd4FxD1IbT6UXK6Xs2HUcuA5srChgsPA-3D-3D9poL_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oy7SOgmTC136V6ZgZzBSpzuHtaQ2AuXld6FsvzHBcY1AxZ4UPkHmYye5M2Yg-2BFdez7JLqxy3PPB69Zj8cyKtN7BBCTpwiCZSyP06tozVRBMch2WaOXuhW1Grc3sLHx8g6rhyxWZHEkCHbcTJ-2BHucDvQ-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">quagga2 1.7.5</a><br>
|
||||
↳ Advanced barcode scanning for browser and Node.</p>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56pgNlYuMEBloKyCCGedODriBujo6avReiHzL6GJEVoEvA-3D-3DtBzD_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEfo20fupbQYUe8XDME2riwHic86vKaZD3HH96n49T-2FlC3N4PtncOiGyu2lrzEJaPZJ4-2BBx96O2a5pGwY5ZEOhhJX-2BZ4eLGEfBTiuY45RRsQZi9NfektirJd7sYicWxhYGRVGpyWXm6a-2BEZq9Gtm23xA-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">lowdb 4.0</a><br>
|
||||
↳ Simple to use local JSON database.</p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 6px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56rOHZ0N3xGeTmVHdceNhoPZxfJFaDKRHwKV1B15qiaW5w-3D-3DJhje_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5omBcR4pD1Ku4heFG7EsNorrN-2FyTChV1xMe7-2F03egbr5hSqIFOVZDyKDwSsERbsUNhwmvss4ReB16IiVOAPAZsB0dk-2FCpqXEiiRHmXqS65QOD0ekMbfB05UGwq8O-2FqC4ysTvBOy6ZtiVUVrc-2FH5W6IKg-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">node-jira-client 8.2</a><br>
|
||||
↳ Node wrapper for Jira's REST API.</p>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qQk-2BpW7foBNGey3rLzMuDo62zZWbrczt015Bj1WlNDBQ-3D-3Dm_3Q_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEsvu6H9oknetn8jsJ2NuiZQd55Mea4qpyKMLbDkN-2BvTC-2FBd-2BWdFatd2Xrl-2BRFWG77QEtsRvdmm8717A0xsHaVh6tNDkLpo6aSpcmVSbIPOX5ook72haTTqHSXZO-2BHmgmhRwEpbRLMMMqVZkapq2gSMA-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Prisma 4.5</a><br>
|
||||
↳ Next-generation ORM. There's <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qQk-2BpW7foBNGey3rLzMuDo62zZWbrczt015Bj1WlNDBQ-3D-3Dzxz3_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEjYQc5ZwzDq6kBdevLrTkqLe1i3-2BTFdcCZxtr66gQyhRf-2BpynzjpmMMtda3K7MVyvOhoQG4k4KqM-2FwzqcxtIoNHfF-2F3kvn73uKwg2z88wcmD0RTrbjCK1CTtcw6qGZ7KMo7GGbkR-2FT3ju57ULscV0AA-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">a lot new here.</a></p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 6px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56phtW2mQRCtGg046i4t6FORw2LuWRPENLor2jpdmT-2Borg-3D-3DNEn8_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5odCf-2FiEfecKVEq6V8FvBCjA5ZwnzYfYJNkionHhlr-2B8FKzcC4tVLDaTd-2BbQCruVnIbAHwS43NJwupmBg6tVBhykIIOmxOPZm-2Bo8RnrWTKVsh9SqHlmrxEZ0qzKrWaapkcCI5HryNu-2BPTNftU3x6DZ8Q-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">RedisSMQ 7.1.1</a><br>
|
||||
↳ High-performance Redis message queue.</p>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56rSNyns-2FbWD08foeryG3PRyYFxJow9Y-2FQxDypnkYk9RxA-3D-3DQqJ4_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEfFX6mz7iCRhL8yCQ2Y7vvv5MBMI-2BSSvYTXJf4BBNL8m-2F5w7VbqSEblu4KLM0cpHtYT9h96A-2Fq-2FkS7ajK-2BnI6iHYTYyY9mzuG5jOFIz563u-2Ftu1RxaPaI5gzf7M-2FduSlja8cPcz8z-2B9bww-2FxpBYibDA-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">PSD 0.3</a><br>
|
||||
↳ Zero-dependency PSD/Photoshop file parser.</p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qk1TR1e5JGImoRII3FmCcfLMz14acCxyGpPNCcSSCeFg-3D-3D6S8P_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiED-2FFw5PhVn2VvXv5tuIgwfjRpdamvTvVOw3guLR3fUWKFse57-2BDwa-2BZay0G8uZBhzL5yF5iiPKHG1-2FbXLhCC2vaXisfDfVUb2euWpE769d93Lap8NPUHBvm6iC7LgnfcFKcaiYkh4mXIFdoB8ONURlQ-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">fdir 5.3</a><br>
|
||||
↳ Performance-oriented directory crawler and globbing library.</p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56rvrBGWXh8OvpamaF-2F9XMSlJHqCP4LlTvUqxgT-2BRA7vrw-3D-3DbaYf_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEbZGielvStiDu5-2BXJ4OTyxG-2BNgh-2Fx70o5ouvVAZEExNV2xLG7Q2rvu1h0VfEIh4VAADpnbn0m4y-2Bhh8xVuySBV8bL5rz25sdMElmQmu8DRiL8sR3WKzRrbRBAWF-2BB3KeFndvfWxJTUwojd8AlucJIXQ-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">google-translate 2.0</a><br>
|
||||
↳ Consume Google's <em>Translate API.</em></p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56pqtvru3vdBpFR9D5FHRZdjLjVCbzNTC6R5tpIZaf77WQ-3D-3D8dq9_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEgqafHY6jFbdTSvNleP6DWWCt4KFWx-2F41A-2BwoIA5LJA2-2FX32uUZpYZTIxnqs77b2IDe0HWMFiZ2ItWb4p25-2F-2B2y8v6L1QEXV-2Bg9d-2Bp7hfqWawGJnRkvqUFBfpg0og6ijGcMgIvH4i3rWQkRVjKgTmQg-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Mercurius 11.1</a><br>
|
||||
↳ Implement GraphQL servers with Fastify.</p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56riH7Sj-2BEdAeaoRtj7QagB2G8aO8QqwKJkSIhJ96LGiGA-3D-3DI6w2_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEwmQ4-2FnGqIgbgzSx0ws5zCsrkxFSbWG8rUm5Lnx4jCJsEvlO-2BRHt0nYEf8B6Sol6shjB3b7EmGk-2Bk1njKf3tu1RhXs6g9cVnqfhB8ISfhPwdDStqDRVQQCcsuOHtbLOpxEgx8Nbz6Ia-2FfxHPVaw7-2F2Q-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Mongoist 2.5.6</a><br>
|
||||
↳ MongoDB driver built with <code>async</code>/<code>await</code> in mind.</p>
|
||||
</li>
|
||||
<li style="color: #222; line-height: 1.35em; margin-bottom: 12px; margin-left: 0px !important;">
|
||||
<p style="margin-top: 0.8em; margin-bottom: 0.8em;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56p-2Bvcoz4gSZMRw1zLNJmqpVZZpuFsV-2FeU0Qpx5T6NarKQ-3D-3D0k4f_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEo4tWAkAnpPnGfOF-2FxNkDvuN7BJXTYUf8CxreuKsPc-2BYBXOFS6jSek5B9jso99JKhwS6-2FGJNrodiS5f88AEhyRnTm-2B5UD4HzTauv7UWZh6-2F4TeICFUR8T9hratmCeqPT9f61CRjaQqNrBGa91ROKg0Q-3D-3D" style="text-decoration: none; color: #20824B; font-weight: 600; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Mojo.js 1.7</a><br>
|
||||
↳ Web framework inspired by Perl's Mojolicious.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</td></tr></table>
|
||||
@ -208,13 +248,13 @@
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="content el-content " style="color: #222; border-collapse: collapse; margin-top: 0 !important;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;"><p style="font-weight: 600; font-size: 1.05em; border-bottom-width: 4px; border-bottom-color: #ddeebb; border-bottom-style: solid; line-height: 1.6em; display: inline-block; margin-top: 0.8em; margin-bottom: 0.8em;">💻 Jobs</p></td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="miniitem item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
<p class="desc" style="color: #5a5a5a; line-height: 1.5em !important; font-size: 0.9em !important; margin-top: 8px; margin-right: 0px; margin-bottom: 6px; margin-left: 0px;"><span style="font-weight: 600; font-size: 1.0em; color: #000;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56oCCho7hNJILUYhAVBBA3S1TVq7lt-2F4p296883g4tFZqg-3D-3D_WAq_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5ouX22auILYVCEthoGEnDW5lZVAxux7cyrNjiLMSPND87DO1UPNRKOXKTnvhToLLaRFLapeb1KcVuMOkIcAHXvLKkONVEFS-2FfXFxUp-2BzE1uJn8kHm2j-2Fg3Tb8ebLjdnRJNKBL3dsUDl-2BAlB2Jr-2FHBObw-3D-3D" style="text-decoration: none; color: #20824B; font-size: 1.2em !important; font-weight: 400; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Full-Stack Engineer (NYC / Remote)</a></span> — 100M+ devices, 100B+ API calls. Radar is looking for Product Engineers to build geospatial dev tools.
|
||||
<br><span class="name" style="color: #bbbbbb !important; margin-top: 4px; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Radar</span>
|
||||
<p class="desc" style="color: #5a5a5a; line-height: 1.5em !important; font-size: 0.9em !important; margin-top: 8px; margin-right: 0px; margin-bottom: 6px; margin-left: 0px;"><span style="font-weight: 600; font-size: 1.0em; color: #000;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qasaHBl0gs3SJ3vQnAMnJPU9aLvIxnDyLU79p-2B357hKQ-3D-3DUK0T_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiE9EG-2FlsMwSwzyj-2FLYV-2BOpCArV8KTUQMFghaDDivuU1JkIx7DA2-2FPKV5N6wl3-2BEpVv-2B0dnopBh1oMKWw4fvhotgaNkLd-2B3Mj3KBTQPBvRDNSJkZtmFxN5NrNgl67kyA09TFnW1NOdXRDrEFvWniM30wA-3D-3D" style="text-decoration: none; color: #20824B; font-size: 1.2em !important; font-weight: 400; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Doppler - A SecretOps Platform Built by Developers for Developers</a></span> — Doppler’s looking for Sr. Full-Stack Engineers to help shape the future of security devtools. TypeScript, React, Express, and Go, <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56oSKY6DSK7ZLDxi40W6JInpRJP4scWVGwujayUkTEfTng-3D-3DIJw4_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEbGvTYlQYJ8HAB-2FAFzp7QyFLv8yUn0YwGp1ugvsWb5tCEeW5TzrwvZkTs2yfYyBD7uDeIhEnR53wDbnTJYCOdAth8jiciYetIA25F4MKNEMMDwBJUP8nZg6q7GrK1EaLvo8lmq4KieLIiKbBovNHaGA-3D-3D" style="font-size: 1.0em !important; text-decoration: none; color: #20824B; font-weight: 400; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">apply here</a>.
|
||||
<br><span class="name" style="color: #bbbbbb !important; margin-top: 4px; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Doppler</span>
|
||||
</p>
|
||||
</td></tr></table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" class="miniitem item " style="border-collapse: collapse; margin-bottom: 4px;"><tr><td style="font-family: -apple-system,BlinkMacSystemFont,Helvetica,sans-serif; font-size: 15px; line-height: 1.48em; border-collapse: collapse; padding-top: 0px; padding-right: 15px; padding-bottom: 0px; padding-left: 15px;">
|
||||
<p class="desc" style="color: #5a5a5a; line-height: 1.5em !important; font-size: 0.9em !important; margin-top: 8px; margin-right: 0px; margin-bottom: 6px; margin-left: 0px;"><span style="font-weight: 600; font-size: 1.0em; color: #000;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56r-2FlaDQrQPsWNriJ2X6cWQi1tqZbpxhHuJGegpNMHxUOA-3D-3DGdCx_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oMskCe2ZO5enlXfI-2Ba8Ii28hKXHrE5lYRoTHZ9tE5kQ6SfxMFVAKDrEg24SVYlDPChcED-2FvQCGg2eb76BFxavDGxggeg0j8V-2FV0CcOHtRyCf5CUiOQJmJhGeeVUY76uYQ4xra1xYBmCgOHewWeJoA5A-3D-3D" style="text-decoration: none; color: #20824B; font-size: 1.2em !important; font-weight: 400; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Find Tech Jobs with Hired</a></span> — Create a profile on Hired to connect with hiring managers at growing startups and Fortune 500 companies. It's free for job-seekers.
|
||||
<p class="desc" style="color: #5a5a5a; line-height: 1.5em !important; font-size: 0.9em !important; margin-top: 8px; margin-right: 0px; margin-bottom: 6px; margin-left: 0px;"><span style="font-weight: 600; font-size: 1.0em; color: #000;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qaMsAShSLTzDOWuV-2FcVV7pRu4mvi82funiiImPN7jlsQ-3D-3D0hXk_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEkoE7xVBorVeUpPXPHEhhga9ZIqhLuS5gW088J84nNV9kNrKsk3TLBHqmJ9WEqKhK2D1l6PXO9DLG6xJC-2FU8ZtcUxJFCVX8DWL-2Fb4yuQaH6gdKaNXrL4OEw8KACiH4Z3FLqvpGFY5WCiQ3UGR8D-2FLeA-3D-3D" style="text-decoration: none; color: #20824B; font-size: 1.2em !important; font-weight: 400; border-bottom-width: 1px; border-bottom-color: #ddd; border-bottom-style: solid;">Find Tech Jobs with Hired</a></span> — Create a profile on Hired to connect with hiring managers at growing startups and Fortune 500 companies. It's free for job-seekers.
|
||||
<br><span class="name" style="color: #bbbbbb !important; margin-top: 4px; text-transform: uppercase; font-size: 12px; line-height: 1.2em;">Hired</span>
|
||||
</p>
|
||||
</td></tr></table>
|
||||
@ -233,9 +273,7 @@
|
||||
|
||||
<hr style="width: 60px; margin-left: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0; border-top-width: 4px; border-top-color: #6ca629; border-top-style: solid;">
|
||||
<p style="font-size: 12px; line-height: 18px; margin-top: 1em; margin-right: 0; margin-bottom: 1em; margin-left: 0;">Published by Cooper Press Ltd.<br>Fairfield Enterprise Centre, Louth, LN11 0LS, United Kingdom</p>
|
||||
<p style="font-size: 0.9em; margin-top: 1em; margin-right: 0; margin-bottom: 1em; margin-left: 0;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qPJxxKJ5QkQnu5plIhQMd7jm32aQFaVAX6ptRkyjULJQ-3D-3D9DWa_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oDDJyGpwbKF75si2KnV-2FEpDtz16teFwAoj8RTQilvBNxjKnW-2B9h6EieCoFFAkNQ9V9c0IQGs2FxlMbHWuJ3mEc-2FsWDAOdeVyDY7QWQEBKFs9CT-2BCSGc92juzMgeOWPurYZYrU-2FL1rIDsa6cBSzHwNqQ-3D-3D" style="text-decoration: underline; color: #20824B;">Cancel your subscription</a> or <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56r2VS7bq5YsZ1xZ3760ZmCZ6VWi-2FtTs5RRBqRDcte3dGA-3D-3DhKMD_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5oeiyJ55USrr-2BfTcupjuZI5XOPKAeGfDPldjflGh4UFubSKBXfvFkyrZTN6W-2B4yG-2B58z4xYiorS-2BsSkcjQSLExL78M-2FACJdWbywRmTlV05JohBsUplijU4q-2FQYETPZAL8oVLRhdPveRmCKx625qNI8dQ-3D-3D" style="text-decoration: underline; color: #20824B;">change your address.</a></p>
|
||||
|
||||
|
||||
<p style="font-size: 0.9em; margin-top: 1em; margin-right: 0; margin-bottom: 1em; margin-left: 0;"><a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56qPJxxKJ5QkQnu5plIhQMd7jm32aQFaVAX6ptRkyjULJQ-3D-3DeWxs_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEEPl0SEXF91axrqwEC2oBokLdmWqeOCIIC537mbhMHd-2B0VxNs62uasjPHaU1IknHbyEINnqxjMM2VkFxwYVLb2ZlxFysQ5V7v2sJTZf-2FO1pD7TIGQPb5AsrYBQ8MbWmMj-2B58LRKsXz9dY5SE2F3h-2BBA-3D-3D" style="text-decoration: underline; color: #20824B;">Cancel your subscription</a> or <a href="https://u25184427.ct.sendgrid.net/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56r2VS7bq5YsZ1xZ3760ZmCZ6VWi-2FtTs5RRBqRDcte3dGA-3D-3DgMfl_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiET-2Br9lddSxpGdW9pWgz1d5SMPt-2Fe3KQ4OmuqL7LJ4-2Fym2nXyQmuI0D1VkdJOW0df79l2GB0wXm7PR4Ac8i2itGyhK7zdrCusB7Fpou3pttBGEBmNDadBBwdczIlxUrEGgaPqavyN8bvx-2FzpCnFCTlKg-3D-3D" style="text-decoration: underline; color: #20824B;">change your address.</a></p>
|
||||
|
||||
|
||||
</td></tr></table>
|
||||
@ -246,5 +284,5 @@
|
||||
<div id="footer" class="noarchive">
|
||||
|
||||
</div>
|
||||
<!-- hey --><img src="https://nodeweekly.com/open/458/4f439e0f78" width="3" height="1" alt="n" /><!-- hey --><img src="https://u25184427.ct.sendgrid.net/wf/open?upn=VbY9PHrcT8wDX1sMvxaoDeFrnDggj0GS9qRxnZZ16E2L1I4jFbZ-2BRZojKJXnL6-2FijMU2353EwpgxEqWgVUoQw4Z6vZHm1RoMgsf8pqVHhr1z-2FeeawIU2Xm5YQsPdCxDttK5YXRA3LCgIW3qNN7jLyE-2BCTS8dvmMgUjHI6-2B68XhCzs3iNRsawgsRDGOK6BpsRiHtCub7oGp8O2tcL-2F0XOVRb8jmo9dlLfKBDrYnAYVhU-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;"/></body>
|
||||
<!-- hey --><img src="https://nodeweekly.com/open/459/4f439e0f78" width="3" height="1" alt="n" /><!-- hey --><img src="https://u25184427.ct.sendgrid.net/wf/open?upn=VbY9PHrcT8wDX1sMvxaoDeFrnDggj0GS9qRxnZZ16E2kKWMv-2F0YoFNKe2ljrs6sKFjImwUy-2Fv-2F2cQdrb32UmSMoveT2xLj6qPsQWtfVmgGO2pRHfMPPUN7ty1sWIEPM8pd-2B8-2BaYYf-2F-2BzLw3biwQf4dnvS6hIWDsNTyMCJs3BqiZTMgikR-2BDVanVA0ig7GTNtppSdLc0DO7AtD-2FhU-2F2QBtXmajObwto-2BVJM-2BbIezjuB4-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;"/></body>
|
||||
</html>
|
||||
|
||||
@ -13,9 +13,9 @@ import { generateUniqueUrl } from '../src/content-handler'
|
||||
import fs from 'fs'
|
||||
import { BeehiivHandler } from '../src/newsletters/beehiiv-handler'
|
||||
import { ConvertkitHandler } from '../src/newsletters/convertkit-handler'
|
||||
import { parseHTML } from 'linkedom'
|
||||
import { GhostHandler } from '../src/newsletters/ghost-handler'
|
||||
import { CooperPressHandler } from '../src/newsletters/cooper-press-handler'
|
||||
import { getNewsletterHandler } from '../src'
|
||||
|
||||
chai.use(chaiAsPromised)
|
||||
chai.use(chaiString)
|
||||
@ -93,104 +93,95 @@ describe('Newsletter email test', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('isProbablyNewsletter', () => {
|
||||
it('returns true for substack newsletter', async () => {
|
||||
describe('getNewsletterHandler', () => {
|
||||
it('returns substack newsletter handler', async () => {
|
||||
const html = load('./test/data/substack-forwarded-newsletter.html')
|
||||
const dom = parseHTML(html).document
|
||||
await expect(
|
||||
new SubstackHandler().isNewsletter({
|
||||
dom,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
).to.eventually.be.true
|
||||
const handler = await getNewsletterHandler({
|
||||
html,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
expect(handler).to.be.instanceOf(SubstackHandler)
|
||||
})
|
||||
it('returns true for private forwarded substack newsletter', async () => {
|
||||
|
||||
it('returns SubstackHandler for private forwarded substack newsletter', async () => {
|
||||
const html = load(
|
||||
'./test/data/substack-private-forwarded-newsletter.html'
|
||||
)
|
||||
const dom = parseHTML(html).document
|
||||
await expect(
|
||||
new SubstackHandler().isNewsletter({
|
||||
dom,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
).to.eventually.be.true
|
||||
const handler = await getNewsletterHandler({
|
||||
html,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
expect(handler).to.be.instanceOf(SubstackHandler)
|
||||
})
|
||||
it('returns false for substack welcome email', async () => {
|
||||
|
||||
it('returns undefined for substack welcome email', async () => {
|
||||
const html = load('./test/data/substack-forwarded-welcome-email.html')
|
||||
const dom = parseHTML(html).document
|
||||
await expect(
|
||||
new SubstackHandler().isNewsletter({
|
||||
dom,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
).to.eventually.be.false
|
||||
const handler = await getNewsletterHandler({
|
||||
html,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
expect(handler).to.be.undefined
|
||||
})
|
||||
it('returns true for beehiiv.com newsletter', async () => {
|
||||
|
||||
it('returns BeehiivHandler for beehiiv.com newsletter', async () => {
|
||||
const html = load('./test/data/beehiiv-newsletter.html')
|
||||
const dom = parseHTML(html).document
|
||||
await expect(
|
||||
new BeehiivHandler().isNewsletter({
|
||||
dom,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
).to.eventually.be.true
|
||||
const handler = await getNewsletterHandler({
|
||||
html,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
expect(handler).to.be.instanceOf(BeehiivHandler)
|
||||
})
|
||||
it('returns true for milkroad newsletter', async () => {
|
||||
|
||||
it('returns BeehiivHandler for milkroad newsletter', async () => {
|
||||
const html = load('./test/data/milkroad-newsletter.html')
|
||||
const dom = parseHTML(html).document
|
||||
await expect(
|
||||
new BeehiivHandler().isNewsletter({
|
||||
dom,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
).to.eventually.be.true
|
||||
const handler = await getNewsletterHandler({
|
||||
html,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
expect(handler).to.be.instanceOf(BeehiivHandler)
|
||||
})
|
||||
it('returns true for ghost newsletter', async () => {
|
||||
|
||||
it('returns GhostHandler for ghost newsletter', async () => {
|
||||
const html = load('./test/data/ghost-newsletter.html')
|
||||
const dom = parseHTML(html).document
|
||||
await expect(
|
||||
new GhostHandler().isNewsletter({
|
||||
dom,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
).to.eventually.be.true
|
||||
const handler = await getNewsletterHandler({
|
||||
html,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
expect(handler).to.be.instanceOf(GhostHandler)
|
||||
})
|
||||
it('returns true for convertkit newsletter', async () => {
|
||||
|
||||
it('returns ConvertkitHandler for convertkit newsletter', async () => {
|
||||
const html = load('./test/data/convertkit-newsletter.html')
|
||||
const dom = parseHTML(html).document
|
||||
await expect(
|
||||
new ConvertkitHandler().isNewsletter({
|
||||
dom,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
).to.eventually.be.true
|
||||
const handler = await getNewsletterHandler({
|
||||
html,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
expect(handler).to.be.instanceOf(ConvertkitHandler)
|
||||
})
|
||||
it('returns true for node-weekly newsletter', async () => {
|
||||
|
||||
it('returns CooperPressHandler for node-weekly newsletter', async () => {
|
||||
const html = load('./test/data/node-weekly-newsletter.html')
|
||||
const dom = parseHTML(html).document
|
||||
await expect(
|
||||
new CooperPressHandler().isNewsletter({
|
||||
dom,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
).to.eventually.be.true
|
||||
const handler = await getNewsletterHandler({
|
||||
html,
|
||||
postHeader: '',
|
||||
from: '',
|
||||
unSubHeader: '',
|
||||
})
|
||||
expect(handler).to.be.instanceOf(CooperPressHandler)
|
||||
})
|
||||
})
|
||||
|
||||
@ -293,18 +284,18 @@ describe('Newsletter email test', () => {
|
||||
before(() => {
|
||||
nock('https://u25184427.ct.sendgrid.net')
|
||||
.head(
|
||||
'/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56o0z9xhskaXR4aYohHPLtwRHfml_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nxtQVfuqJiLh7Fio3fEtt5ouN4IH56AfszUQpxY-2FQ233kp0bjSZhBBVWAB43dgKumQkDW-2BxDFnQIUpvhmEgzSJq-2FMRG00GM7fkZVuPU-2BX8cdg8AGRHUU9Qhw6W67XEMkJVygTdm70Mo9ypNi8N33hgmhM3F6un9s7p1K1Gq-2FunslA-3D-3D'
|
||||
'/ls/click?upn=MnmHBiCwIPe9TmIJeskmA7mFdqmsIs-2B5Xs-2FNpSIs56obSPDXnoBEjufvIqRCEJUf5Uqg_vVXscVLXlj5UtQe3aqo5RMTdTq2PepdZjP86UOmA8nyFE700vlj1-2FK27spZiPEiEkDU3SIXWGeoiU60KFhM-2B-2Bxx5yiL8KKbAV6oFceRi8O1gMc3mdwg5D8FaaM3PublaX24iAcVbn99PzxJaPuVrU6xDWbRovw2UgGTIoEI-2BBO-2B0qzi2wv5c6yJTkUGZOcsJ6xGLXO1BO-2BHSbyZMZV4NMw-3D-3D'
|
||||
)
|
||||
.reply(301, undefined, {
|
||||
Location: 'https://nodeweekly.com/issues/458',
|
||||
Location: 'https://nodeweekly.com/issues/459',
|
||||
})
|
||||
nock('https://nodeweekly.com').head('/issues/458').reply(200, '')
|
||||
nock('https://nodeweekly.com').head('/issues/459').reply(200, '')
|
||||
})
|
||||
|
||||
it('gets the URL from the header', async () => {
|
||||
const html = load('./test/data/node-weekly-newsletter.html')
|
||||
const url = await new CooperPressHandler().findNewsletterUrl(html)
|
||||
expect(url).to.startWith('https://nodeweekly.com/issues/458')
|
||||
expect(url).to.startWith('https://nodeweekly.com/issues/459')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user