@stacksjs/email 0.72.5 → 0.72.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/template.d.ts +12 -0
- package/dist/template.js +1 -1
- package/package.json +5 -5
package/dist/template.d.ts
CHANGED
|
@@ -18,6 +18,18 @@
|
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
20
|
export declare function safe(html: string): SafeHtml;
|
|
21
|
+
/**
|
|
22
|
+
* HTML-escape every char that could break out of a text node into an
|
|
23
|
+
* attribute / tag context. The five-char set is the OWASP minimum for
|
|
24
|
+
* "in a text node or quoted attribute"; we don't need the more
|
|
25
|
+
* paranoid (forward-slash, equals, etc.) set because the template uses
|
|
26
|
+
* `{{ … }}` only inside the document body, never inside `<script>` /
|
|
27
|
+
* `<style>` / unquoted attribute slots.
|
|
28
|
+
*
|
|
29
|
+
* Constructed once at module load — a `replace` chain is faster than a
|
|
30
|
+
* single regex for short strings.
|
|
31
|
+
*/
|
|
32
|
+
export declare function escapeHtml(input: string): string;
|
|
21
33
|
/**
|
|
22
34
|
* Render an email template with optional layout
|
|
23
35
|
*
|
package/dist/template.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{config}from"@stacksjs/config";import{log}from"@stacksjs/logging";import{fs}from"@stacksjs/storage";import{defaultsResourcesPath,resourcesPath}from"@stacksjs/path";import{join}from"node:path";import{inlineCss,shouldInlineByDefault}from"./css-inliner";export class SafeHtml{value;__safeHtml=!0;constructor(value){this.value=value}}export function safe(html){return new SafeHtml(html)}function getDefaultVariables(){const primaryColor=config.app.primaryColor||"#3b82f6";return{appName:config.app.name||"Stacks",appUrl:config.app.url||"https://localhost",primaryColor,primaryColorDark:darkenColor(primaryColor,15),year:new Date().getFullYear()}}function darkenColor(hex,percent){const num=Number.parseInt(hex.replace("#",""),16),amt=Math.round(2.55*percent),R=Math.max(0,(num>>16)-amt),G=Math.max(0,(num>>8&255)-amt),B=Math.max(0,(num&255)-amt);return`#${(16777216+R*65536+G*256+B).toString(16).slice(1)}`}function escapeHtml(input){return input.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function replaceVariables(html,variables){let result=html;for(const[key,value]of Object.entries(variables)){const escapedKey=key.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),regex=new RegExp(`\\{\\{\\s*${escapedKey}\\s*\\}\\}`,"g");result=result.replace(regex,renderTemplateValue(value))}return result}function renderTemplateValue(value){if(value===null||value===void 0)return"";if(value instanceof SafeHtml)return value.value;return escapeHtml(String(value))}const templateRoots=[(relativePath)=>resourcesPath(join("emails",relativePath)),(relativePath)=>defaultsResourcesPath(join("emails",relativePath))];function resolveTemplatePath(templateName){for(const root of templateRoots){if(templateName.endsWith(".stx")){const fullPath=root(templateName);if(fs.existsSync(fullPath))return{path:fullPath,type:"stx"};continue}if(templateName.endsWith(".html")){const fullPath=root(templateName);if(fs.existsSync(fullPath))return{path:fullPath,type:"html"};continue}const stxPath=root(`${templateName}.stx`);if(fs.existsSync(stxPath))return{path:stxPath,type:"stx"};const htmlPath=root(`${templateName}.html`);if(fs.existsSync(htmlPath))return{path:htmlPath,type:"html"}}return null}function loadHtmlTemplate(templatePath){const path=templatePath.endsWith(".html")?templatePath:`${templatePath}.html`;for(const root of templateRoots){const fullPath=root(path);if(fs.existsSync(fullPath))return fs.readFileSync(fullPath,"utf-8")}return null}function loadLayout(layoutName){return loadHtmlTemplate(`layouts/${layoutName}`)}function htmlToText(html){return html.replace(/<br\s*\/?>/gi,`
|
|
1
|
+
import{config}from"@stacksjs/config";import{log}from"@stacksjs/logging";import{fs}from"@stacksjs/storage";import{defaultsResourcesPath,resourcesPath}from"@stacksjs/path";import{join}from"node:path";import{inlineCss,shouldInlineByDefault}from"./css-inliner";export class SafeHtml{value;__safeHtml=!0;constructor(value){this.value=value}}export function safe(html){return new SafeHtml(html)}function getDefaultVariables(){const primaryColor=config.app.primaryColor||"#3b82f6";return{appName:config.app.name||"Stacks",appUrl:config.app.url||"https://localhost",primaryColor,primaryColorDark:darkenColor(primaryColor,15),year:new Date().getFullYear()}}function darkenColor(hex,percent){const num=Number.parseInt(hex.replace("#",""),16),amt=Math.round(2.55*percent),R=Math.max(0,(num>>16)-amt),G=Math.max(0,(num>>8&255)-amt),B=Math.max(0,(num&255)-amt);return`#${(16777216+R*65536+G*256+B).toString(16).slice(1)}`}export function escapeHtml(input){return input.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function replaceVariables(html,variables){let result=html;for(const[key,value]of Object.entries(variables)){const escapedKey=key.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),regex=new RegExp(`\\{\\{\\s*${escapedKey}\\s*\\}\\}`,"g");result=result.replace(regex,renderTemplateValue(value))}return result}function renderTemplateValue(value){if(value===null||value===void 0)return"";if(value instanceof SafeHtml)return value.value;return escapeHtml(String(value))}const templateRoots=[(relativePath)=>resourcesPath(join("emails",relativePath)),(relativePath)=>defaultsResourcesPath(join("emails",relativePath))];function resolveTemplatePath(templateName){for(const root of templateRoots){if(templateName.endsWith(".stx")){const fullPath=root(templateName);if(fs.existsSync(fullPath))return{path:fullPath,type:"stx"};continue}if(templateName.endsWith(".html")){const fullPath=root(templateName);if(fs.existsSync(fullPath))return{path:fullPath,type:"html"};continue}const stxPath=root(`${templateName}.stx`);if(fs.existsSync(stxPath))return{path:stxPath,type:"stx"};const htmlPath=root(`${templateName}.html`);if(fs.existsSync(htmlPath))return{path:htmlPath,type:"html"}}return null}function loadHtmlTemplate(templatePath){const path=templatePath.endsWith(".html")?templatePath:`${templatePath}.html`;for(const root of templateRoots){const fullPath=root(path);if(fs.existsSync(fullPath))return fs.readFileSync(fullPath,"utf-8")}return null}function loadLayout(layoutName){return loadHtmlTemplate(`layouts/${layoutName}`)}function htmlToText(html){return html.replace(/<br\s*\/?>/gi,`
|
|
2
2
|
`).replace(/<\/(p|div|h[1-6]|li|tr)>/gi,`
|
|
3
3
|
`).replace(/<\/td>/gi,"\t").replace(/<[^>]*>/g,"").replace(/ /g," ").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/©/g,"(c)").replace(/\n\s*\n\s*\n/g,`
|
|
4
4
|
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/email",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.72.
|
|
5
|
+
"version": "0.72.7",
|
|
6
6
|
"description": "The Stacks Email integration. Painlessly create & manage your inboxes, templates, and send emails.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -64,10 +64,10 @@
|
|
|
64
64
|
"postal-mime": "^2.7.6"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"@stacksjs/cli": "0.72.
|
|
68
|
-
"@stacksjs/config": "0.72.
|
|
67
|
+
"@stacksjs/cli": "0.72.7",
|
|
68
|
+
"@stacksjs/config": "0.72.7",
|
|
69
69
|
"better-dx": "^0.2.23",
|
|
70
|
-
"@stacksjs/error-handling": "0.72.
|
|
71
|
-
"@stacksjs/types": "0.72.
|
|
70
|
+
"@stacksjs/error-handling": "0.72.7",
|
|
71
|
+
"@stacksjs/types": "0.72.7"
|
|
72
72
|
}
|
|
73
73
|
}
|