@paroicms/contact-form-plugin 0.24.1 → 0.26.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.
package/backend/dist/plugin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { strVal } from "@paroi/data-formatters-lib";
|
|
2
|
-
import { escapeHtml, loadSimpleTranslatorFromDirectory, resolveModuleDirectory, } from "@paroicms/public-server-lib";
|
|
2
|
+
import { escapeHtml, loadSimpleTranslatorFromDirectory, makeStylesheetLinkAsyncTag, resolveModuleDirectory, } from "@paroicms/public-server-lib";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { sendContactFormMail } from "./contact-form-mail.js";
|
|
@@ -17,14 +17,19 @@ const plugin = {
|
|
|
17
17
|
languages: ["en", "fr"],
|
|
18
18
|
logger: service.logger,
|
|
19
19
|
});
|
|
20
|
-
service.setPublicAssetsDirectory(join(packageDir, "
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
[
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
service.setPublicAssetsDirectory(join(packageDir, "frontend", "dist"));
|
|
21
|
+
service.registerHeadTags(({ state }) => {
|
|
22
|
+
if (!state.has("paContactForm"))
|
|
23
|
+
return;
|
|
24
|
+
return [
|
|
25
|
+
`<script type="module" src="${service.pluginAssetsUrl}/contact-form-plugin.mjs" class="js-script-${SLUG}" data-google-recaptcha-site-key="${escapeHtml(service.configuration.googleRecaptchaSiteKey)}" async></script>`,
|
|
26
|
+
makeStylesheetLinkAsyncTag(`${service.pluginAssetsUrl}/contact-form-plugin.css`),
|
|
27
|
+
];
|
|
28
|
+
});
|
|
29
|
+
service.registerLiquidTag("contactForm", "injectHtml", (service) => {
|
|
30
|
+
service.setRenderState("paContactForm", true);
|
|
31
|
+
return `<div data-effect="paContactForm" data-home-url="${escapeHtml(service.homeUrl)}"></div>`;
|
|
32
|
+
});
|
|
28
33
|
service.setPublicApiHandler(async (service, httpContext, relativePath) => {
|
|
29
34
|
const { req, res } = httpContext;
|
|
30
35
|
if (relativePath !== "") {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{template as $,insert as o,setAttribute as g,createComponent as M,effect as P,render as ae}from"https://esm.sh/solid-js@1.9.7/web";import{createMemo as re,createSignal as d,Show as I,onMount as oe,onCleanup as ce}from"https://esm.sh/solid-js@1.9.7";function le(e){return e.varName?` for '${e.varName}'`:""}function B(e,t={}){if(e==null||e===""&&!t.allowEmpty)throw new Error(`Missing string value${le(t)}`);return typeof e=="string"?e:e.toString()}const J=e=>e!=null&&(e=Object.getPrototypeOf(e),e===Array.prototype||e===Object.prototype);function V(e,t,a){for(const[n,c]of Object.entries(t)){const m=`${a}.${n}`;e[m]=c,J(c)&&V(e,c,m)}}function ie(e){const t={...e};for(const[a,n]of Object.entries(e))J(n)&&V(t,n,a);return t}const de=(e,t)=>{if(t)for(const[a,n]of Object.entries(t))e=e.replace(new RegExp(`{{\\s*${a}\\s*}}`,"g"),n);return e},ue=e=>e;function me(e,t=ue){return(a,...n)=>{a[0]==="."&&(a=a.slice(1));const c=e()?.[a];switch(typeof c){case"function":return c(...n);case"string":return t(c,n[0]);default:return c}}}const pe="Name",fe="Email",ge="Subject",he="Message",be="Send",ve="johndoe@gmail.com",Pe="John Doe",$e="The subject of your message",ye="Enter your message here…",Ee="Unexpected error, the message could not be sent.",we="Return Home",Fe="Your message has been sent. If there is a response, it will be sent to the address:",Se={name:pe,email:fe,subject:ge,message:he,send:be,emailPlaceholder:ve,namePlaceholder:Pe,subjectPlaceholder:$e,messagePlaceholder:ye,unexpectedErrorMessage:Ee,returnHome:we,successMessage:Fe},xe="Nom",_e="Courriel",Me="Sujet",je="Message",Ce="Envoyer",Re="johndoe@gmail.com",Le="John Doe",ke="Le sujet de votre message",He="Saisissez votre message…",Oe="Erreur inattendue, le message n'a pas pu être envoyé.",Te="Retourner à l'accueil",Ne="Votre message a été envoyé. S'il y a une réponse, elle sera envoyée à l'adresse :",Ae={name:xe,email:_e,subject:Me,message:je,send:Ce,emailPlaceholder:Re,namePlaceholder:Le,subjectPlaceholder:ke,messagePlaceholder:He,unexpectedErrorMessage:Oe,returnHome:Te,successMessage:Ne},U={en:Se,fr:Ae};function De(e){const t=re((()=>{const n=e in U?e:"en";return ie(U[n])}));return{t:me(t,de)}}async function Ie(e,t,a){a(!0);try{const n=await Ue(e);return t.reset(),n}finally{a(!1)}}async function Ue(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 n=await t.text();throw new Error(`Unexpected error: ${n}`)}return await t.json()}var qe=$("<div class=PaForm-error>"),Be=$('<div class=PaForm-ended><div class=PaForm-message><p> <i></i></p></div><div class=PaForm-action><a class="PaForm-button PaButton">'),Je=$('<form class=PaForm><div class=PaForm-fields><label class=PaField><span class=PaField-label></span><input class=PaField-input type=text name=name required></label><label class=PaField><span class=PaField-label></span><input class=PaField-input type=email name=email required></label><label class=PaField><span class=PaField-label></span><textarea class=PaField-input rows=5 name=message required></textarea></label></div><div class=PaForm-action><button class="PaForm-button PaButton"type=submit>'),Ve=$("<div class=PaForm-captcha><div class=g-recaptcha data-callback=onRecaptchaSubmitted data-expired-callback=onRecaptchaExpired>");function ze({googleRecaptchaSiteKey:e,language:t,homeUrl:a}){const[n,c]=d(""),[m,G]=d(""),[j,Y]=d(""),[Q,W]=d(),[C,R]=d(!e),[L,y]=d(),[X,k]=d(""),[Z,K]=d(!1),{t:r}=De(t),ee=async l=>{try{if(l.preventDefault(),!C()||!h)throw new Error("Recaptcha error");const i=await Ie({language:t,name:n(),message:j(),email:m(),gRecaptchaResponse:Q()},h,K);i.success?y(!0):(y(!1),k(i.message??r("unexpectedErrorMessage")))}catch{y(!1),k(r("unexpectedErrorMessage"))}},h=(()=>{var l=Je(),i=l.firstChild,H=i.firstChild,O=H.firstChild,E=O.nextSibling,T=H.nextSibling,N=T.firstChild,w=N.nextSibling,ne=T.nextSibling,A=ne.firstChild,F=A.nextSibling,S=i.nextSibling,x=S.firstChild;return l.addEventListener("submit",ee),o(O,(()=>r("name"))),E.addEventListener("change",(s=>c(s.currentTarget.value))),o(N,(()=>r("email"))),w.addEventListener("change",(s=>{G(s.currentTarget.value)})),o(A,(()=>r("message"))),F.addEventListener("change",(s=>Y(s.currentTarget.value))),o(l,e&&(()=>{var s=Ve(),u=s.firstChild;return g(u,"data-sitekey",e),s})(),S),o(l,M(I,{get when(){return L()===!1},get children(){var s=qe();return o(s,X),s}}),S),o(x,(()=>r("send"))),o(l,M(I,{get when(){return L()===!0},get children(){var s=Be(),u=s.firstChild,p=u.firstChild,f=p.firstChild,b=f.nextSibling,v=u.nextSibling,D=v.firstChild;return o(p,(()=>r("successMessage")),f),o(b,m),g(D,"href",a),o(D,(()=>r("returnHome"))),s}}),null),P((s=>{var u=r("namePlaceholder"),p=r("emailPlaceholder"),f=r("messagePlaceholder"),b=!!Z(),v=!C();return u!==s.e&&g(E,"placeholder",s.e=u),p!==s.t&&g(w,"placeholder",s.t=p),f!==s.a&&g(F,"placeholder",s.a=f),b!==s.o&&x.classList.toggle("inProgress",s.o=b),v!==s.i&&(x.disabled=s.i=v),s}),{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0}),P((()=>E.value=n())),P((()=>w.value=m())),P((()=>F.value=j())),l})();return oe((()=>{e&&(window.onRecaptchaSubmitted=te,window.onRecaptchaExpired=se)})),ce((()=>{e&&(window.onRecaptchaSubmitted=void 0,window.onRecaptchaExpired=void 0)})),h;function te(l){if(!l)return;R(!0);const i=h?.elements.namedItem("g-recaptcha-response");W(i.value)}function se(){R(!1)}}let z;const[_]=document.getElementsByClassName("js-script-contact-form");_&&_ instanceof HTMLScriptElement&&(z=B(_.dataset.googleRecaptchaSiteKey,{varName:"data-google-recaptcha-site-key"}));function Ge(e,{language:t}){if(!t)throw new Error("Missing language");e.dataset.recaptchaKey&&console.warn('Remove "data-recaptcha-key" attribute, it is not needed anymore.');const a=B(e.dataset.homeUrl),n=document.createElement("script");n.setAttribute("src","https://www.google.com/recaptcha/api.js"),document.head.appendChild(n),ae((()=>M(ze,{googleRecaptchaSiteKey:z,language:t,homeUrl:a})),e)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",q):q();function q(){const e=document.documentElement.lang,t=document.querySelector("[data-effect='paContactForm']");t&&Ge(t,{language:e})}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paroicms/contact-form-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "Contact form plugin for ParoiCMS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"paroicms",
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
"type": "module",
|
|
19
19
|
"main": "backend/dist/plugin.js",
|
|
20
20
|
"scripts": {
|
|
21
|
-
"dev:public": "(cd
|
|
21
|
+
"dev:public": "(cd frontend && vite)",
|
|
22
22
|
"build": "npm run build:backend && npm run build:public",
|
|
23
23
|
"build:backend": "(cd backend && tsc)",
|
|
24
|
-
"build:public": "(cd
|
|
25
|
-
"minify:public": "terser
|
|
26
|
-
"build:public:watch": "(cd
|
|
27
|
-
"clear": "rimraf backend/dist/*
|
|
24
|
+
"build:public": "(cd frontend && tsc && vite build && npm run minify:public)",
|
|
25
|
+
"minify:public": "terser frontend/dist/contact-form-plugin.mjs --output frontend/dist/contact-form-plugin.mjs",
|
|
26
|
+
"build:public:watch": "(cd frontend && tsc && vite build --watch)",
|
|
27
|
+
"clear": "rimraf backend/dist/* frontend/dist/*"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@paroi/data-formatters-lib": "~0.4.0"
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"@paroicms/public-server-lib": "0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@paroicms/public-anywhere-lib": "0.
|
|
38
|
-
"@paroicms/public-server-lib": "0.
|
|
37
|
+
"@paroicms/public-anywhere-lib": "0.24.0",
|
|
38
|
+
"@paroicms/public-server-lib": "0.36.0",
|
|
39
39
|
"@solid-primitives/i18n": "~2.2.1",
|
|
40
40
|
"@types/node": "~24.0.1",
|
|
41
41
|
"rimraf": "~6.0.1",
|
|
@@ -50,6 +50,6 @@
|
|
|
50
50
|
"files": [
|
|
51
51
|
"backend/dist",
|
|
52
52
|
"backend/locales",
|
|
53
|
-
"
|
|
53
|
+
"frontend/dist"
|
|
54
54
|
]
|
|
55
55
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{template as $,insert as o,setAttribute as g,createComponent as M,effect as P,render as ne}from"https://esm.sh/solid-js@1.9.7/web";import{createMemo as ae,createSignal as d,Show as A,onMount as re,onCleanup as oe}from"https://esm.sh/solid-js@1.9.7";function ce(e){return e.varName?` for '${e.varName}'`:""}function q(e,t={}){if(e==null||e===""&&!t.allowEmpty)throw new Error(`Missing string value${ce(t)}`);return typeof e=="string"?e:e.toString()}const B=e=>e!=null&&(e=Object.getPrototypeOf(e),e===Array.prototype||e===Object.prototype);function J(e,t,a){for(const[n,c]of Object.entries(t)){const m=`${a}.${n}`;e[m]=c,B(c)&&J(e,c,m)}}function le(e){const t={...e};for(const[a,n]of Object.entries(e))B(n)&&J(t,n,a);return t}const ie=(e,t)=>{if(t)for(const[a,n]of Object.entries(t))e=e.replace(new RegExp(`{{\\s*${a}\\s*}}`,"g"),n);return e},de=e=>e;function ue(e,t=de){return(a,...n)=>{a[0]==="."&&(a=a.slice(1));const c=e()?.[a];switch(typeof c){case"function":return c(...n);case"string":return t(c,n[0]);default:return c}}}const me="Name",pe="Email",fe="Subject",ge="Message",he="Send",be="johndoe@gmail.com",ve="John Doe",Pe="The subject of your message",$e="Enter your message here…",ye="Unexpected error, the message could not be sent.",Ee="Return Home",we="Your message has been sent. If there is a response, it will be sent to the address:",Se={name:me,email:pe,subject:fe,message:ge,send:he,emailPlaceholder:be,namePlaceholder:ve,subjectPlaceholder:Pe,messagePlaceholder:$e,unexpectedErrorMessage:ye,returnHome:Ee,successMessage:we},Fe="Nom",xe="Courriel",_e="Sujet",Me="Message",je="Envoyer",Ce="johndoe@gmail.com",Re="John Doe",Le="Le sujet de votre message",ke="Saisissez votre message…",He="Erreur inattendue, le message n'a pas pu être envoyé.",Oe="Retourner à l'accueil",Te="Votre message a été envoyé. S'il y a une réponse, elle sera envoyée à l'adresse :",Ne={name:Fe,email:xe,subject:_e,message:Me,send:je,emailPlaceholder:Ce,namePlaceholder:Re,subjectPlaceholder:Le,messagePlaceholder:ke,unexpectedErrorMessage:He,returnHome:Oe,successMessage:Te},U={en:Se,fr:Ne};function De(e){const t=ae((()=>{const n=e in U?e:"en";return le(U[n])}));return{t:ue(t,ie)}}async function Ie(e,t,a){a(!0);try{const n=await Ae(e);return t.reset(),n}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 n=await t.text();throw new Error(`Unexpected error: ${n}`)}return await t.json()}var Ue=$("<div class=PaForm-error>"),qe=$('<div class=PaForm-ended><div class=PaForm-message><p> <i></i></p></div><div class=PaForm-action><a class="PaForm-button PaButton">'),Be=$('<form class=PaForm><div class=PaForm-fields><label class=PaField><span class=PaField-label></span><input class=PaField-input type=text name=name required></label><label class=PaField><span class=PaField-label></span><input class=PaField-input type=email name=email required></label><label class=PaField><span class=PaField-label></span><textarea class=PaField-input rows=5 name=message required></textarea></label></div><div class=PaForm-action><button class="PaForm-button PaButton"type=submit>'),Je=$("<div class=PaForm-captcha><div class=g-recaptcha data-callback=onRecaptchaSubmitted data-expired-callback=onRecaptchaExpired>");function Ve({googleRecaptchaKey:e,language:t,homeUrl:a}){const[n,c]=d(""),[m,z]=d(""),[j,G]=d(""),[Y,Q]=d(),[C,R]=d(!e),[L,y]=d(),[W,k]=d(""),[X,Z]=d(!1),{t:r}=De(t),K=async l=>{try{if(l.preventDefault(),!C()||!h)throw new Error("Recaptcha error");const i=await Ie({language:t,name:n(),message:j(),email:m(),gRecaptchaResponse:Y()},h,Z);i.success?y(!0):(y(!1),k(i.message??r("unexpectedErrorMessage")))}catch{y(!1),k(r("unexpectedErrorMessage"))}},h=(()=>{var l=Be(),i=l.firstChild,H=i.firstChild,O=H.firstChild,E=O.nextSibling,T=H.nextSibling,N=T.firstChild,w=N.nextSibling,se=T.nextSibling,D=se.firstChild,S=D.nextSibling,F=i.nextSibling,x=F.firstChild;return l.addEventListener("submit",K),o(O,(()=>r("name"))),E.addEventListener("change",(s=>c(s.currentTarget.value))),o(N,(()=>r("email"))),w.addEventListener("change",(s=>{z(s.currentTarget.value)})),o(D,(()=>r("message"))),S.addEventListener("change",(s=>G(s.currentTarget.value))),o(l,e&&(()=>{var s=Je(),u=s.firstChild;return g(u,"data-sitekey",e),s})(),F),o(l,M(A,{get when(){return L()===!1},get children(){var s=Ue();return o(s,W),s}}),F),o(x,(()=>r("send"))),o(l,M(A,{get when(){return L()===!0},get children(){var s=qe(),u=s.firstChild,p=u.firstChild,f=p.firstChild,b=f.nextSibling,v=u.nextSibling,I=v.firstChild;return o(p,(()=>r("successMessage")),f),o(b,m),g(I,"href",a),o(I,(()=>r("returnHome"))),s}}),null),P((s=>{var u=r("namePlaceholder"),p=r("emailPlaceholder"),f=r("messagePlaceholder"),b=!!X(),v=!C();return u!==s.e&&g(E,"placeholder",s.e=u),p!==s.t&&g(w,"placeholder",s.t=p),f!==s.a&&g(S,"placeholder",s.a=f),b!==s.o&&x.classList.toggle("inProgress",s.o=b),v!==s.i&&(x.disabled=s.i=v),s}),{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0}),P((()=>E.value=n())),P((()=>w.value=m())),P((()=>S.value=j())),l})();return re((()=>{e&&(window.onRecaptchaSubmitted=ee,window.onRecaptchaExpired=te)})),oe((()=>{e&&(window.onRecaptchaSubmitted=void 0,window.onRecaptchaExpired=void 0)})),h;function ee(l){if(!l)return;R(!0);const i=h?.elements.namedItem("g-recaptcha-response");Q(i.value)}function te(){R(!1)}}let V;const[_]=document.getElementsByClassName("js-script-contact-form");_&&_ instanceof HTMLScriptElement&&(V=q(_.dataset.googleRecaptchaKey,{varName:"data-google-recaptcha-key"}));function ze(e,{language:t}){if(!t)throw new Error("Missing language");e.dataset.recaptchaKey&&console.warn('Remove "data-recaptcha-key" attribute, it is not needed anymore.');const a=q(e.dataset.homeUrl),n=document.createElement("script");n.setAttribute("src","https://www.google.com/recaptcha/api.js"),document.head.appendChild(n),ne((()=>M(Ve,{googleRecaptchaKey:V,language:t,homeUrl:a})),e)}document.addEventListener("DOMContentLoaded",(()=>{const e=document.documentElement.lang,t=document.querySelector("[data-effect='paContactForm']");t&&ze(t,{language:e})}));
|
/package/{public-front/dist/public-front-plugin.css → frontend/dist/contact-form-plugin.css}
RENAMED
|
File without changes
|