@paroicms/contact-form-plugin 0.17.2 → 0.19.0
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.
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const data_formatters_lib_1 = require("@paroi/data-formatters-lib");
|
|
5
|
-
const public_server_lib_1 = require("@paroicms/public-server-lib");
|
|
6
|
-
async function sendContactFormMail(service, input, i18n) {
|
|
1
|
+
import { messageOf, strValOrUndef } from "@paroi/data-formatters-lib";
|
|
2
|
+
import { escapeHtml, } from "@paroicms/public-server-lib";
|
|
3
|
+
export async function sendContactFormMail(service, input, i18n) {
|
|
7
4
|
const { email, name, message, subject, gRecaptchaResponse } = input;
|
|
8
5
|
let contactEmail;
|
|
9
6
|
try {
|
|
10
|
-
contactEmail =
|
|
7
|
+
contactEmail = strValOrUndef(await service.getSiteFieldValue({
|
|
11
8
|
fieldName: "contactEmail",
|
|
12
9
|
language: input.language,
|
|
13
10
|
}));
|
|
@@ -28,14 +25,14 @@ async function sendContactFormMail(service, input, i18n) {
|
|
|
28
25
|
html: `<p>${i18n.translate({
|
|
29
26
|
key: "nameIs",
|
|
30
27
|
language: input.language,
|
|
31
|
-
args: [
|
|
28
|
+
args: [escapeHtml(name)],
|
|
32
29
|
})}</p>
|
|
33
30
|
<p>${i18n.translate({
|
|
34
31
|
key: "emailIs",
|
|
35
32
|
language: input.language,
|
|
36
|
-
args: [
|
|
33
|
+
args: [escapeHtml(email)],
|
|
37
34
|
})}</p>
|
|
38
|
-
<p>${
|
|
35
|
+
<p>${escapeHtml(message, { newLinesToBr: true })}</p>`,
|
|
39
36
|
});
|
|
40
37
|
return {
|
|
41
38
|
success: true,
|
|
@@ -44,7 +41,7 @@ async function sendContactFormMail(service, input, i18n) {
|
|
|
44
41
|
catch (err) {
|
|
45
42
|
if (err)
|
|
46
43
|
throw err;
|
|
47
|
-
service.logger.error(`fail to send mail: ${
|
|
44
|
+
service.logger.error(`fail to send mail: ${messageOf(err)}`);
|
|
48
45
|
return {
|
|
49
46
|
success: false,
|
|
50
47
|
message: contactEmail
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.formatSendMailInput = formatSendMailInput;
|
|
4
|
-
const data_formatters_lib_1 = require("@paroi/data-formatters-lib");
|
|
5
|
-
function formatSendMailInput(data) {
|
|
1
|
+
import { strVal, strValOrUndef } from "@paroi/data-formatters-lib";
|
|
2
|
+
export function formatSendMailInput(data) {
|
|
6
3
|
return {
|
|
7
|
-
language:
|
|
8
|
-
email:
|
|
9
|
-
name:
|
|
10
|
-
subject:
|
|
11
|
-
message:
|
|
12
|
-
gRecaptchaResponse:
|
|
4
|
+
language: strVal(data.language),
|
|
5
|
+
email: strVal(data.email),
|
|
6
|
+
name: strVal(data.name),
|
|
7
|
+
subject: strValOrUndef(data.subject),
|
|
8
|
+
message: strVal(data.message),
|
|
9
|
+
gRecaptchaResponse: strValOrUndef(data.gRecaptchaResponse),
|
|
13
10
|
};
|
|
14
11
|
}
|
package/backend/dist/plugin.js
CHANGED
|
@@ -1,24 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const version = (0, data_formatters_lib_1.strVal)(require((0, node_path_1.join)(packageDir, "package.json")).version);
|
|
1
|
+
import { strVal } from "@paroi/data-formatters-lib";
|
|
2
|
+
import { escapeHtml, loadSimpleTranslatorFromDirectory, resolveModuleDirectory, } from "@paroicms/public-server-lib";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { sendContactFormMail } from "./contact-form-mail.js";
|
|
6
|
+
import { formatSendMailInput } from "./data-format.js";
|
|
7
|
+
const projectDir = resolveModuleDirectory(import.meta.url, { parent: true });
|
|
8
|
+
const packageDir = dirname(projectDir);
|
|
9
|
+
const version = strVal(JSON.parse(readFileSync(join(packageDir, "package.json"), "utf-8")).version);
|
|
11
10
|
const plugin = {
|
|
12
11
|
version,
|
|
13
12
|
slug: "contact-form",
|
|
14
13
|
async siteInit(service) {
|
|
15
|
-
const simpleI18n = await
|
|
16
|
-
l10nDir:
|
|
14
|
+
const simpleI18n = await loadSimpleTranslatorFromDirectory({
|
|
15
|
+
l10nDir: join(projectDir, "locales"),
|
|
17
16
|
languages: ["en", "fr"],
|
|
18
17
|
logger: service.logger,
|
|
19
18
|
});
|
|
20
|
-
service.setPublicAssetsDirectory(
|
|
21
|
-
service.addHeadTag(`<link rel="stylesheet" href="${
|
|
19
|
+
service.setPublicAssetsDirectory(join(packageDir, "public-front", "dist"));
|
|
20
|
+
service.addHeadTag(`<link rel="stylesheet" href="${escapeHtml(`${service.pluginAssetsUrl}/public-front-plugin.css`)}">`, `<script type="module" src="${escapeHtml(`${service.pluginAssetsUrl}/public-front-plugin.mjs`)}"></script>`);
|
|
22
21
|
service.setPublicApiHandler(async (service, req, res, relativePath) => {
|
|
23
22
|
if (relativePath !== "") {
|
|
24
23
|
res.status(404).send({ status: 404 });
|
|
@@ -26,15 +25,15 @@ const plugin = {
|
|
|
26
25
|
}
|
|
27
26
|
let input;
|
|
28
27
|
try {
|
|
29
|
-
input =
|
|
28
|
+
input = formatSendMailInput(req.body);
|
|
30
29
|
}
|
|
31
30
|
catch (error) {
|
|
32
31
|
res.status(400).send({ status: 400, message: error.message });
|
|
33
32
|
return;
|
|
34
33
|
}
|
|
35
|
-
const result = await
|
|
34
|
+
const result = await sendContactFormMail(service, input, simpleI18n);
|
|
36
35
|
res.send(result);
|
|
37
36
|
});
|
|
38
37
|
},
|
|
39
38
|
};
|
|
40
|
-
|
|
39
|
+
export default plugin;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paroicms/contact-form-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "Contact form plugin for ParoiCMS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"paroicms",
|
|
@@ -15,12 +15,14 @@
|
|
|
15
15
|
},
|
|
16
16
|
"author": "Paroi Team",
|
|
17
17
|
"license": "MIT",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "backend/dist/plugin.js",
|
|
18
20
|
"scripts": {
|
|
19
21
|
"dev:public": "(cd public-front && vite)",
|
|
20
22
|
"build": "npm run build:backend && npm run build:public",
|
|
21
23
|
"build:backend": "(cd backend && tsc)",
|
|
22
24
|
"build:public": "(cd public-front && tsc && vite build && npm run minify:public)",
|
|
23
|
-
"minify:public": "terser
|
|
25
|
+
"minify:public": "terser public-front/dist/public-front-plugin.mjs --output public-front/dist/public-front-plugin.mjs",
|
|
24
26
|
"build:public:watch": "(cd public-front && tsc && vite build --watch)",
|
|
25
27
|
"clear": "rimraf backend/dist/* public-front/dist/*"
|
|
26
28
|
},
|
|
@@ -32,20 +34,19 @@
|
|
|
32
34
|
"@paroicms/public-server-lib": "0"
|
|
33
35
|
},
|
|
34
36
|
"devDependencies": {
|
|
35
|
-
"@paroicms/public-anywhere-lib": "0.
|
|
36
|
-
"@paroicms/public-server-lib": "0.
|
|
37
|
+
"@paroicms/public-anywhere-lib": "0.19.0",
|
|
38
|
+
"@paroicms/public-server-lib": "0.26.0",
|
|
37
39
|
"@solid-primitives/i18n": "~2.1.1",
|
|
38
|
-
"@types/node": "~22.10
|
|
40
|
+
"@types/node": "~22.13.10",
|
|
39
41
|
"rimraf": "~6.0.1",
|
|
40
|
-
"sass": "~1.
|
|
42
|
+
"sass": "~1.84.0",
|
|
41
43
|
"solid-devtools": "~0.33.0",
|
|
42
44
|
"solid-js": "1.9.4",
|
|
43
|
-
"typescript": "~5.
|
|
44
|
-
"vite": "~6.0
|
|
45
|
+
"typescript": "~5.8.2",
|
|
46
|
+
"vite": "~6.1.0",
|
|
45
47
|
"vite-plugin-solid": "~2.11.0",
|
|
46
48
|
"terser": "~5.37.0"
|
|
47
49
|
},
|
|
48
|
-
"main": "backend/dist/plugin.js",
|
|
49
50
|
"files": [
|
|
50
51
|
"backend/dist",
|
|
51
52
|
"backend/locales",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{insert as c,setAttribute as
|
|
1
|
+
import{template as F,insert as c,setAttribute as f,createComponent as M,effect as $,render as K}from"https://esm.sh/solid-js@1.9.4/web";import{createMemo as ee,createSignal as d,Show as D,onMount as te,onCleanup as ne}from"https://esm.sh/solid-js@1.9.4";function se(e){return e.varName?` for '${e.varName}'`:""}function ae(e,t={}){if(e==null||e===""&&!t.allowEmpty)throw new Error(`Missing string value${se(t)}`);return typeof e=="string"?e:e.toString()}var N=e=>e!=null&&(e=Object.getPrototypeOf(e),e===Array.prototype||e===Object.prototype);function U(e,t,a){for(const[s,r]of Object.entries(t)){const m=`${a}.${s}`;e[m]=r,N(r)&&U(e,r,m)}}function re(e){const t={...e};for(const[a,s]of Object.entries(e))N(s)&&U(t,s,a);return t}var oe=(e,t)=>{if(t)for(const[a,s]of Object.entries(t))e=e.replace(new RegExp(`{{\\s*${a}\\s*}}`,"g"),s);return e},ce=e=>e;function le(e,t=ce){return(a,...s)=>{a[0]==="."&&(a=a.slice(1));const r=e()?.[a];switch(typeof r){case"function":return r(...s);case"string":return t(r,s[0]);default:return r}}}const ie="Name",de="Email",ue="Subject",me="Message",pe="Send",ge="johndoe@gmail.com",fe="John Doe",he="The subject of your message",ve="Enter your message here…",be="Unexpected error, the message could not be sent.",$e="Return Home",Fe="Your message has been sent. If there is a response, it will be sent to the address:",Ce={name:ie,email:de,subject:ue,message:me,send:pe,emailPlaceholder:ge,namePlaceholder:fe,subjectPlaceholder:he,messagePlaceholder:ve,unexpectedErrorMessage:be,returnHome:$e,successMessage:Fe},Ee="Nom",we="Courriel",ye="Sujet",Se="Message",xe="Envoyer",Me="johndoe@gmail.com",_e="John Doe",Re="Le sujet de votre message",je="Saisissez votre message…",Pe="Erreur inattendue, le message n'a pas pu être envoyé.",Le="Retourner à l'accueil",Oe="Votre message a été envoyé. S'il y a une réponse, elle sera envoyée à l'adresse :",He={name:Ee,email:we,subject:ye,message:Se,send:xe,emailPlaceholder:Me,namePlaceholder:_e,subjectPlaceholder:Re,messagePlaceholder:je,unexpectedErrorMessage:Pe,returnHome:Le,successMessage:Oe},I={en:Ce,fr:He};function Te(e){const t=ee((()=>{const s=e in I?e:"en";return re(I[s])}));return{t:le(t,oe)}}async function ke(e,t,a){a(!0);try{const s=await Ae(e);return t.reset(),s}finally{a(!1)}}async function Ae(e){const t=await fetch("/api/plugin/contact-form",{headers:{"Content-Type":"application/json"},body:JSON.stringify(e),method:"POST"});if(t.status!==200){const s=await t.text();throw new Error(`Unexpected error: ${s}`)}return await t.json()}var De=F("<div class=ContactForm-error>"),Ie=F('<div class="ContactForm-done ContactForm-ended"><div class=ContactForm-endedMessage><p></p><p></p></div><div class=ContactForm-endedActions><a class=BigBtn>'),Ne=F("<form class=ContactForm><div class=ContactForm-fieldGroup><label class=ContactFormField><span class=ContactFormField-label></span><input class=ContactFormField-input type=text name=name required></label><label class=ContactFormField><span class=ContactFormField-label></span><input class=ContactFormField-input type=email name=email required></label><label class=ContactFormField><span class=ContactFormField-label></span><textarea class=ContactFormField-textarea rows=5 name=message required></textarea></label></div><div class=ContactForm-action><button type=submit class=ContactForm-btn>"),Ue=F("<div class=ContactForm-captcha><div class=g-recaptcha data-callback=onRecaptchaSubmitted data-expired-callback=onRecaptchaExpired>");function qe({recaptchaKey:e,language:t,homeUrl:a}){const[s,r]=d(""),[m,q]=d(""),[_,J]=d(""),[B,G]=d(),[R,j]=d(!e),[P,C]=d(),[V,L]=d(""),[z,Y]=d(!1),{t:o}=Te(t),Q=async l=>{try{if(l.preventDefault(),!R()||!h)throw new Error("Erreur de recaptcha");const i=await ke({language:t,name:s(),message:_(),email:m(),gRecaptchaResponse:B()},h,Y);i.success?C(!0):(C(!1),L(i.message??o("unexpectedErrorMessage")))}catch{C(!1),L(o("unexpectedErrorMessage"))}},h=(()=>{var l=Ne(),i=l.firstChild,O=i.firstChild,H=O.firstChild,E=H.nextSibling,T=O.nextSibling,k=T.firstChild,w=k.nextSibling,Z=T.nextSibling,A=Z.firstChild,y=A.nextSibling,S=i.nextSibling,x=S.firstChild;return l.addEventListener("submit",Q),c(H,(()=>o("name"))),E.addEventListener("change",(n=>r(n.currentTarget.value))),c(k,(()=>o("email"))),w.addEventListener("change",(n=>{q(n.currentTarget.value)})),c(A,(()=>o("message"))),y.addEventListener("change",(n=>J(n.currentTarget.value))),c(l,e&&(()=>{var n=Ue(),u=n.firstChild;return f(u,"data-sitekey",e),n})(),S),c(l,M(D,{get when(){return P()===!1},get children(){var n=De();return c(n,V),n}}),S),c(x,(()=>o("send"))),c(l,M(D,{get when(){return P()===!0},get children(){var n=Ie(),u=n.firstChild,p=u.firstChild,v=p.nextSibling,b=u.nextSibling,g=b.firstChild;return c(p,(()=>o("successMessage"))),c(v,m),f(g,"href",a),c(g,(()=>o("returnHome"))),n}}),null),$((n=>{var u=o("namePlaceholder"),p=o("emailPlaceholder"),v=o("messagePlaceholder"),b=!!z(),g=!R();return u!==n.e&&f(E,"placeholder",n.e=u),p!==n.t&&f(w,"placeholder",n.t=p),v!==n.a&&f(y,"placeholder",n.a=v),b!==n.o&&x.classList.toggle("inProgress",n.o=b),g!==n.i&&(x.disabled=n.i=g),n}),{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0}),$((()=>E.value=s())),$((()=>w.value=m())),$((()=>y.value=_())),l})();return te((()=>{e&&(window.onRecaptchaSubmitted=W,window.onRecaptchaExpired=X)})),ne((()=>{e&&(window.onRecaptchaSubmitted=void 0,window.onRecaptchaExpired=void 0)})),h;function W(l){if(!l)return;j(!0);const i=h?.elements.namedItem("g-recaptcha-response");G(i.value)}function X(){j(!1)}}function Je(e,{language:t}){if(!t)throw new Error("Missing language");const a=e.dataset.recaptchaKey,s=ae(e.dataset.homeUrl),r=document.createElement("script");r.setAttribute("src","https://www.google.com/recaptcha/api.js"),document.head.appendChild(r),K((()=>M(qe,{recaptchaKey:a,language:t,homeUrl:s})),e)}document.addEventListener("DOMContentLoaded",(()=>{const e=document.documentElement.lang,t=document.querySelector("[data-effect='contactForm']");t&&Je(t,{language:e})}));
|