@beforesemicolon/site-builder 0.1.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/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2023, Before Semicolon
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # Markup
2
+
3
+ Reactive HTML Templating System
4
+
5
+ [![Static Badge](https://img.shields.io/badge/Website-blue)](https://markup.beforesemicolon.com)
6
+ [![MD Docs](https://img.shields.io/badge/MD_docs-blue)](https://github.com/beforesemicolon/markup/blob/main/docs/index.md)
7
+ [![npm](https://img.shields.io/npm/v/%40beforesemicolon%2Fmarkup)](https://www.npmjs.com/package/@beforesemicolon/markup)
8
+ ![npm](https://img.shields.io/npm/l/%40beforesemicolon%2Fmarkup)
9
+ [![Test](https://github.com/beforesemicolon/html/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/beforesemicolon/html/actions/workflows/test.yml)
10
+
11
+ Markup is a JavaScript reactive templating system built to simplify how you build Web user interfaces using web standards with minimal enhancements to the native web APIs as possible.
12
+
13
+ It consists of 3 main APIs with additional utilities to simplify things even further:
14
+
15
+ - `html`: A JavaScript tagged function that allows you to represent the DOM using template literal string;
16
+ - `state`: A simple state tracking API that allows you to define reactive data as you wish;
17
+ - `effect`: A straight forward way to define things that need to happen when certain states change;
18
+
19
+ ### Motivation
20
+
21
+ JavaScript, Web Standards and APIs give you everything you need to build any web project you want. What is often painful to deal with is the DOM and reactivity, especially as the project gets bigger or require multiple people collaboration.
22
+
23
+ Markup was created to give you all the reactivity you need while making it simple to define your HTML in JavaScript without introducing a new syntax, or requiring a build, or a big library you need to ship to the client.
24
+
25
+ From this:
26
+
27
+ ```javascript
28
+ let count = 0
29
+
30
+ // tedious DOM definition and manipulation
31
+ const p = document.createElement('p')
32
+ p.textContent = `count: ${count}`
33
+
34
+ const btn = document.createElement('button')
35
+ btn.type = 'button'
36
+ btn.textContent = 'count up'
37
+
38
+ // limiting event driven
39
+ btn.addEventListener('onclick', () => {
40
+ count += 1
41
+ p.textContent = `count: ${count}`
42
+
43
+ if (count > 10) {
44
+ alert('You counted passed 10!')
45
+ }
46
+ })
47
+
48
+ document.body.append(p, btn)
49
+ ```
50
+
51
+ To this:
52
+
53
+ ```javascript
54
+ // reactive data
55
+ const [count, updateCount] = state(0)
56
+
57
+ // data driven
58
+ effect(() => {
59
+ if (count() > 10) {
60
+ alert('You counted passed 10!')
61
+ }
62
+ })
63
+
64
+ const countUp = () => {
65
+ updateCount((prev) => prev + 1)
66
+ }
67
+
68
+ // reactive DOM/templates
69
+ html`
70
+ <p>count: ${count}</p>
71
+ <button type="button" onclick="${countUp}">count up</button>
72
+ `.render(document.body)
73
+ ```
74
+
75
+ ### How does it work?
76
+
77
+ Markup uses [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) and [Functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions) to do everything.
78
+
79
+ - **Functions**: JavaScript functions are perfect for lazy evaluations which makes it perfect for reactivity. Markup uses functions everywhere, from internals, defining state, effects, utilities, etc.
80
+ - **Template Literals**: The template literal is used to represent HTML in JavaScript and to avoid to reinvent the wheel. Everything else is enforced by web standards.
81
+
82
+ Literally everything else is how you know it to be in plain HTML, CSS and JavaScript.
83
+
84
+ We believe in a simple way to build the web without the jargon of a framework, complex project setups, new syntax, all to spit out HTML, CSS and JavaScript at the end.
85
+
86
+ #### Examples
87
+
88
+ This is a simple example of a button, but you can check:
89
+
90
+ - [A Modular Todo App](https://stackblitz.com/edit/web-platform-lvonxr?file=app.js)
91
+ - [A Simple Counter App](https://stackblitz.com/edit/web-platform-adqrrf?file=app.js)
92
+ - [A Simple Time App](https://stackblitz.com/edit/web-platform-bwoxex?file=button.js)
93
+
94
+ ## Install
95
+
96
+ ```
97
+ npm install @beforesemicolon/markup
98
+ ```
99
+
100
+ or
101
+
102
+ ```
103
+ yarn add @beforesemicolon/markup
104
+ ```
105
+
106
+ ## Use directly in the Browser
107
+
108
+ This library requires no build or parsing. The CDN package is one digit killobyte in size, tiny!
109
+
110
+ ```html
111
+ <!doctype html>
112
+ <html lang="en">
113
+ <head>
114
+ <!-- Grab the latest version -->
115
+ <script src="https://unpkg.com/@beforesemicolon/markup/dist/client.js"></script>
116
+
117
+ <!-- Or a specific version -->
118
+ <script src="https://unpkg.com/@beforesemicolon/markup@0.3.0/dist/client.js"></script>
119
+ </head>
120
+ </html>
121
+ ```
122
+
123
+ ### Usage
124
+
125
+ ```html
126
+ <div id="app"></div>
127
+
128
+ <script>
129
+ const { html, state, effect } = BFS.MARKUP
130
+
131
+ html`<h1>Hello World</h1>`.render(document.getElementById('app'))
132
+ </script>
133
+ ```
@@ -0,0 +1 @@
1
+ "use strict";var a=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var t=(r,o,p,x)=>{if(o&&typeof o=="object"||typeof o=="function")for(let m of c(o))!d.call(r,m)&&m!==p&&a(r,m,{get:()=>o[m],enumerable:!(x=b(o,m))||x.enumerable});return r},f=(r,o,p)=>(t(r,o,"default"),p&&t(p,o,"default"));var g=r=>t(a({},"__esModule",{value:!0}),r);var e={};module.exports=g(e);f(e,require("./types.js"),module.exports);f(e,require("./parse-template.js"),module.exports);0&&(module.exports={...require("./types.js"),...require("./parse-template.js")});
@@ -0,0 +1,25 @@
1
+ "use strict";var g=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var D=Object.prototype.hasOwnProperty;var y=(e,n)=>g(e,"name",{value:n,configurable:!0});var K=(e,n)=>{for(var r in n)g(e,r,{get:n[r],enumerable:!0})},V=(e,n,r,f)=>{if(n&&typeof n=="object"||typeof n=="function")for(let i of U(n))!D.call(e,i)&&i!==r&&g(e,i,{get:()=>n[i],enumerable:!(f=F(n,i))||f.enumerable});return e};var _=e=>V(g({},"__esModule",{value:!0}),e);var z={};K(z,{parseTemplate:()=>q});module.exports=_(z);var P=require("./utils/input-definitions-to-object.js"),O=require("./utils/replace-string-value.js"),E=require("./utils/turn-camel-to-kebab-casing.js"),v=require("./utils/merge-objects.js");const x=new Map,T=new Map,S={fetchWidget:async()=>null,fetchTemplate:async()=>null,prod:!1},q=y(async(e,n=S)=>{if(T.set(e.id,e),e.extends){const t=T.get(e.extends)||await n.fetchTemplate(e.extends);if(!t)throw new Error(`Template "${e.extends}" not found`);T.set(e.extends,t),e=(0,v.mergeObjects)(t,e)}const{metadata:r={},scripts:f=[],stylesheets:i=[],links:d=[],fonts:m=[],favicons:c=[],content:h="",manifest:s,...a}=e??{},W=new Map,A=typeof h=="string"?h:await k(h,a,W,n);r.charset||(r.charset="UTF-8"),r.viewport||(r.viewport="width=device-width, initial-scale=1.0");const C=Object.entries(r).map(([t,o])=>t.startsWith("property:")?`<meta property="${t.replace("property:","")}" content="${o}">`:`<meta name="${t}" content="${o}">`).join("");let u="";d.forEach(t=>{let o="<link ";Object.entries(t).forEach(([l,j])=>{o+=`${l}="${j}" `}),u+=o+"/>"});let b="";c.forEach(t=>{let o="<link ";Object.entries(t).forEach(([l,j])=>{o+=`${l}="${l==="href"?"./assets/favicons/":""}${j}" `}),b+=o+"/>"});let w="";m.forEach(t=>{w+=`<link rel="preload" href="./assets/fonts/${t}" as="font" crossorigin="anonymous">`});let p="";[...i,...Array.from(W.entries())].forEach(t=>{if(typeof t=="string")t.startsWith("http")?p+=`<link rel="stylesheet" href="${t}" >`:t.endsWith(".css")?p+=`<link rel="stylesheet" href="./stylesheets/${t}">`:p+=`<style>${t}</style>`;else if(Array.isArray(t)){const[o,l]=t;p+=`<style id="${o}">${M(l)}</style>`}else p+="<style",Object.entries(t.attributes).forEach(([o,l])=>{p+=`${o}="${l}" `}),p+="></style>"});let $="";return f.forEach(t=>{typeof t=="string"?t.startsWith("http")?$+=`<script src="${t}"></script>`:t.endsWith(".js")?$+=`<script src="./scripts/${t}"></script>`:$+=`<script>${t}</script>`:($+="<script ",Object.entries(t).forEach(([o,l])=>{$+=`${o}="${l}" `}),$+="></script>")}),`<!doctype html>
2
+ <html lang="${a.lang??"en"}">
3
+ <head>
4
+ <title>${a.title}</title>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <!-- og -->
8
+ <meta property="og:title" content="${a.title}">
9
+ <meta property="og:type" content="website">
10
+ <meta property="og:description" content="${a.description}">
11
+ <meta property="og:image" content="${a.image}">
12
+ <meta property="og:url" content="${a.domain}">
13
+ <meta property="og:site_name" content="${a.title}">
14
+ ${C?`<!-- metas -->${C}`:""}
15
+ ${b?`<!-- favicons -->${b}`:""}
16
+ ${w?`<!-- fonts -->${w}`:""}
17
+ ${u?`<!-- links -->${u}`:""}
18
+ ${s?`<link rel="manifest" href="./assets/${s}">`:""}
19
+ ${p?`<!-- stylesheets -->${p}`:""}
20
+ </head>
21
+ <body>
22
+ ${A}
23
+ ${$?"<!-- scripts -->"+$:""}
24
+ </body>
25
+ </html>`.replace(/\s{2,}/g," ").replace(/[\t\n]+/g,"")},"parseTemplate");function M(e){return typeof e=="string"?e:Object.entries(e).map(([n,r])=>typeof r=="object"?`${(0,E.turnCamelToKebabCasing)(n)} { ${M(r)} }`:`${(0,E.turnCamelToKebabCasing)(n)}: ${r};`).join(" ")}y(M,"parseStyle");async function k(e,n={},r,f=S){return(await Promise.all(e.map(async i=>{if(typeof i=="string")return(0,O.replaceStringValue)(i,n);let{name:d,children:m,...c}=i;if(d==="widget"){if(i["data-render-id"]=i["data-render-id"]||Math.random().toString(36).substring(2,15),{name:d,children:m,...c}=i,c.id){const s=x.get(c.id)||await f.fetchWidget(c.id);s&&(typeof s.render=="function"?m=[s.render({...(0,P.inputDefinitionsToObject)(s.inputs),...c,env:n})]:m=s.content?[s.content]:[],s.style&&r.set(c.id,s.style),x.set(c.id,s))}if(f.prod)return m.join("")}const h=Object.entries(c).map(([s,a])=>(typeof a=="string"&&(a=(0,O.replaceStringValue)(a,n)),`${s}="${a}"`)).join(" ");return`<${d}`+(h?` ${h}`:"")+`>${await k(m,n,r,f)}</${d}>`}))).join("")}y(k,"parseContent");0&&(module.exports={parseTemplate});
@@ -0,0 +1 @@
1
+ "use strict";var r=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var o=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var l=(e,t,s,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of o(t))!a.call(e,n)&&n!==s&&r(e,n,{get:()=>t[n],enumerable:!(i=g(t,n))||i.enumerable});return e};var p=e=>l(r({},"__esModule",{value:!0}),e);var c={};module.exports=p(c);
@@ -0,0 +1 @@
1
+ "use strict";var u=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var i=(t,e)=>u(t,"name",{value:e,configurable:!0});var p=(t,e)=>{for(var o in e)u(t,o,{get:e[o],enumerable:!0})},c=(t,e,o,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of s(e))!a.call(t,r)&&r!==o&&u(t,r,{get:()=>e[r],enumerable:!(n=l(e,r))||n.enumerable});return t};var d=t=>c(u({},"__esModule",{value:!0}),t);var k={};p(k,{deepValue:()=>f});module.exports=d(k);const f=i((t,e)=>String(e??"").split(".").filter(Boolean).reduce((n,r)=>{try{return n&&typeof n=="object"?n[r]:void 0}catch{return null}},t),"deepValue");0&&(module.exports={deepValue});
@@ -0,0 +1 @@
1
+ "use strict";var o=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var u=(e,t)=>o(e,"name",{value:t,configurable:!0});var c=(e,t)=>{for(var i in t)o(e,i,{get:t[i],enumerable:!0})},j=(e,t,i,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of s(t))!a.call(e,n)&&n!==i&&o(e,n,{get:()=>t[n],enumerable:!(r=b(t,n))||r.enumerable});return e};var l=e=>j(o({},"__esModule",{value:!0}),e);var D={};c(D,{inputDefinitionsToObject:()=>f});module.exports=l(D);function f(e){return e.reduce((t,{name:i,value:r,type:n,definitions:p=[]})=>{switch(n){case"group":t[i]=f(p);break;default:t[i]=r}return t},{})}u(f,"inputDefinitionsToObject");0&&(module.exports={inputDefinitionsToObject});
@@ -0,0 +1 @@
1
+ "use strict";var o=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var u=Object.prototype.hasOwnProperty;var i=(e,r)=>o(e,"name",{value:r,configurable:!0});var c=(e,r)=>{for(var t in r)o(e,t,{get:r[t],enumerable:!0})},a=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let y of s(r))!u.call(e,y)&&y!==t&&o(e,y,{get:()=>r[y],enumerable:!(n=f(r,y))||n.enumerable});return e};var l=e=>a(o({},"__esModule",{value:!0}),e);var w={};c(w,{mergeObjects:()=>A});module.exports=l(w);function A(e,r){if(e===null||typeof e!="object"||r===null||typeof r!="object")return r;if(Array.isArray(e)&&Array.isArray(r))return Array.from(new Set([...e,...r]));const t=Array.isArray(e)?[...e]:{...e};for(const n in r)r.hasOwnProperty(n)&&(Array.isArray(e[n])&&Array.isArray(r[n])?t[n]=Array.from(new Set([...e[n],...r[n]])):t[n]=A(t[n],r[n]));return t}i(A,"mergeObjects");0&&(module.exports={mergeObjects});
@@ -0,0 +1 @@
1
+ "use strict";var c=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var o=(e,n)=>c(e,"name",{value:n,configurable:!0});var u=(e,n)=>{for(var r in n)c(e,r,{get:n[r],enumerable:!0})},a=(e,n,r,l)=>{if(n&&typeof n=="object"||typeof n=="function")for(let t of s(n))!m.call(e,t)&&t!==r&&c(e,t,{get:()=>n[t],enumerable:!(l=p(n,t))||l.enumerable});return e};var d=e=>a(c({},"__esModule",{value:!0}),e);var h={};u(h,{replaceStringValue:()=>f});module.exports=d(h);var i=require("./deep-value.js");const f=o((e,n)=>{let r=null;for(;(r=/{{([a-z0-9.$_]+)}}/gim.exec(e))!==null;){const[l,t]=r,g=(0,i.deepValue)(n,t);e=e.replace(l,String(g))}return e},"replaceStringValue");0&&(module.exports={replaceStringValue});
@@ -0,0 +1 @@
1
+ "use strict";var r=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var A=Object.getOwnPropertyNames;var Z=Object.prototype.hasOwnProperty;var i=(e,t)=>r(e,"name",{value:t,configurable:!0});var c=(e,t)=>{for(var n in t)r(e,n,{get:t[n],enumerable:!0})},g=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of A(t))!Z.call(e,a)&&a!==n&&r(e,a,{get:()=>t[a],enumerable:!(o=s(t,a))||o.enumerable});return e};var m=e=>g(r({},"__esModule",{value:!0}),e);var l={};c(l,{turnCamelToKebabCasing:()=>h});module.exports=m(l);const h=i(e=>{const t=e.match(/(?:[A-Z]+(?=[A-Z][a-z])|[A-Z]+|[a-zA-Z])[^A-Z]*/g);if(t){for(let n=0;n<t.length;n++)t[n]=t[n].toLowerCase();return t.join("-")}return name},"turnCamelToKebabCasing");0&&(module.exports={turnCamelToKebabCasing});
package/dist/client.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";(()=>{var Z=Object.defineProperty;var c=(t,e)=>Z(t,"name",{value:e,configurable:!0});function b(t){return t.reduce((e,{name:n,value:i,type:s,definitions:f=[]})=>{switch(s){case"group":e[n]=b(f);break;default:e[n]=i}return e},{})}c(b,"inputDefinitionsToObject");var C=c((t,e)=>String(e??"").split(".").filter(Boolean).reduce((i,s)=>{try{return i&&typeof i=="object"?i[s]:void 0}catch{return null}},t),"deepValue");var O=c((t,e)=>{let n=null;for(;(n=/{{([a-z0-9.$_]+)}}/gim.exec(t))!==null;){let[i,s]=n,f=C(e,s);t=t.replace(i,String(f))}return t},"replaceStringValue");var A=c(t=>{let e=t.match(/(?:[A-Z]+(?=[A-Z][a-z])|[A-Z]+|[a-zA-Z])[^A-Z]*/g);if(e){for(let n=0;n<e.length;n++)e[n]=e[n].toLowerCase();return e.join("-")}return name},"turnCamelToKebabCasing");function T(t,e){if(t===null||typeof t!="object"||e===null||typeof e!="object")return e;if(Array.isArray(t)&&Array.isArray(e))return Array.from(new Set([...t,...e]));let n=Array.isArray(t)?[...t]:{...t};for(let i in e)e.hasOwnProperty(i)&&(Array.isArray(t[i])&&Array.isArray(e[i])?n[i]=Array.from(new Set([...t[i],...e[i]])):n[i]=T(n[i],e[i]));return n}c(T,"mergeObjects");var E=new Map,k=new Map,W={fetchWidget:async()=>null,fetchTemplate:async()=>null,prod:!1},P=c(async(t,e=W)=>{if(k.set(t.id,t),t.extends){let r=k.get(t.extends)||await e.fetchTemplate(t.extends);if(!r)throw new Error(`Template "${t.extends}" not found`);k.set(t.extends,r),t=T(r,t)}let{metadata:n={},scripts:i=[],stylesheets:s=[],links:f=[],fonts:y=[],favicons:p=[],content:$="",manifest:o,...l}=t??{},S=new Map,M=typeof $=="string"?$:await D($,l,S,e);n.charset||(n.charset="UTF-8"),n.viewport||(n.viewport="width=device-width, initial-scale=1.0");let x=Object.entries(n).map(([r,a])=>r.startsWith("property:")?`<meta property="${r.replace("property:","")}" content="${a}">`:`<meta name="${r}" content="${a}">`).join(""),g="";f.forEach(r=>{let a="<link ";Object.entries(r).forEach(([m,j])=>{a+=`${m}="${j}" `}),g+=a+"/>"});let h="";p.forEach(r=>{let a="<link ";Object.entries(r).forEach(([m,j])=>{a+=`${m}="${m==="href"?"./assets/favicons/":""}${j}" `}),h+=a+"/>"});let w="";y.forEach(r=>{w+=`<link rel="preload" href="./assets/fonts/${r}" as="font" crossorigin="anonymous">`});let d="";[...s,...Array.from(S.entries())].forEach(r=>{if(typeof r=="string")r.startsWith("http")?d+=`<link rel="stylesheet" href="${r}" >`:r.endsWith(".css")?d+=`<link rel="stylesheet" href="./stylesheets/${r}">`:d+=`<style>${r}</style>`;else if(Array.isArray(r)){let[a,m]=r;d+=`<style id="${a}">${L(m)}</style>`}else d+="<style",Object.entries(r.attributes).forEach(([a,m])=>{d+=`${a}="${m}" `}),d+="></style>"});let u="";return i.forEach(r=>{typeof r=="string"?r.startsWith("http")?u+=`<script src="${r}"><\/script>`:r.endsWith(".js")?u+=`<script src="./scripts/${r}"><\/script>`:u+=`<script>${r}<\/script>`:(u+="<script ",Object.entries(r).forEach(([a,m])=>{u+=`${a}="${m}" `}),u+="><\/script>")}),`<!doctype html>
2
+ <html lang="${l.lang??"en"}">
3
+ <head>
4
+ <title>${l.title}</title>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <!-- og -->
8
+ <meta property="og:title" content="${l.title}">
9
+ <meta property="og:type" content="website">
10
+ <meta property="og:description" content="${l.description}">
11
+ <meta property="og:image" content="${l.image}">
12
+ <meta property="og:url" content="${l.domain}">
13
+ <meta property="og:site_name" content="${l.title}">
14
+ ${x?`<!-- metas -->${x}`:""}
15
+ ${h?`<!-- favicons -->${h}`:""}
16
+ ${w?`<!-- fonts -->${w}`:""}
17
+ ${g?`<!-- links -->${g}`:""}
18
+ ${o?`<link rel="manifest" href="./assets/${o}">`:""}
19
+ ${d?`<!-- stylesheets -->${d}`:""}
20
+ </head>
21
+ <body>
22
+ ${M}
23
+ ${u?"<!-- scripts -->"+u:""}
24
+ </body>
25
+ </html>`.replace(/\s{2,}/g," ").replace(/[\t\n]+/g,"")},"parseTemplate");function L(t){return typeof t=="string"?t:Object.entries(t).map(([e,n])=>typeof n=="object"?`${A(e)} { ${L(n)} }`:`${A(e)}: ${n};`).join(" ")}c(L,"parseStyle");async function D(t,e={},n,i=W){return(await Promise.all(t.map(async s=>{if(typeof s=="string")return O(s,e);let{name:f,children:y,...p}=s;if(f==="widget"){if(s["data-render-id"]=s["data-render-id"]||Math.random().toString(36).substring(2,15),{name:f,children:y,...p}=s,p.id){let o=E.get(p.id)||await i.fetchWidget(p.id);o&&(typeof o.render=="function"?y=[o.render({...b(o.inputs),...p,env:e})]:y=o.content?[o.content]:[],o.style&&n.set(p.id,o.style),E.set(p.id,o))}if(i.prod)return y.join("")}let $=Object.entries(p).map(([o,l])=>(typeof l=="string"&&(l=O(l,e)),`${o}="${l}"`)).join(" ");return`<${f}`+($?` ${$}`:"")+`>${await D(y,e,n,i)}</${f}>`}))).join("")}c(D,"parseContent");window&&(window.BFS={...window.BFS||{},SITE_BUILDER:{parseTemplate:P}});})();
26
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/utils/input-definitions-to-object.ts", "../src/utils/deep-value.ts", "../src/utils/replace-string-value.ts", "../src/utils/turn-camel-to-kebab-casing.ts", "../src/utils/merge-objects.ts", "../src/parse-template.ts", "../src/client.ts"],
4
+ "sourcesContent": ["import { ObjectLiteral, InputDefinition } from '../types.ts'\n\nexport function inputDefinitionsToObject(inputDefinitions: InputDefinition[]) {\n return inputDefinitions.reduce(\n (acc, { name, value, type, definitions = [] }) => {\n switch (type) {\n case 'group':\n acc[name] = inputDefinitionsToObject(definitions)\n break\n default:\n acc[name] = value\n }\n\n return acc\n },\n {} as ObjectLiteral\n )\n}\n", "import { ObjectLiteral } from '../types.ts'\n\nexport const deepValue = (obj: ObjectLiteral | unknown[], key: string) => {\n const keyParts = String(key ?? '')\n .split('.')\n .filter(Boolean)\n\n return keyParts.reduce((acc, k) => {\n try {\n // @ts-expect-error No index signature with a parameter of type string\n return acc && typeof acc === 'object' ? acc[k] : undefined\n } catch (e) {\n return null\n }\n }, obj) as unknown\n}\n", "import { deepValue } from './deep-value.ts'\n\nexport const replaceStringValue = (\n value: string,\n data: Record<string, unknown>\n) => {\n let match = null\n\n while ((match = /{{([a-z0-9.$_]+)}}/gim.exec(value)) !== null) {\n const [full, key] = match\n const dv = deepValue(data, key)\n\n value = value.replace(full, String(dv))\n }\n\n return value\n}\n", "export const turnCamelToKebabCasing = (str: string) => {\n const match = str.match(/(?:[A-Z]+(?=[A-Z][a-z])|[A-Z]+|[a-zA-Z])[^A-Z]*/g)\n\n if (match) {\n for (let i = 0; i < match.length; i++) {\n match[i] = match[i].toLowerCase()\n }\n\n return match.join('-')\n }\n\n return name\n}\n", "export function mergeObjects(a: unknown, b: unknown) {\n if (a === null || typeof a !== 'object') return b\n if (b === null || typeof b !== 'object') return b\n\n if (Array.isArray(a) && Array.isArray(b)) {\n return Array.from(new Set([...a, ...b]))\n }\n\n const obj = Array.isArray(a) ? [...a] : { ...a }\n\n for (const key in b) {\n if (b.hasOwnProperty(key)) {\n // @ts-expect-error a or b in unknown\n if (Array.isArray(a[key]) && Array.isArray(b[key])) {\n // @ts-expect-error a or b in unknown\n obj[key] = Array.from(new Set([...a[key], ...b[key]]))\n } else {\n // @ts-expect-error a or b in unknown\n obj[key] = mergeObjects(obj[key], b[key])\n }\n }\n }\n\n return obj\n}\n", "import { Template, Style, TemplateContent, Widget } from './types.ts'\nimport { inputDefinitionsToObject } from './utils/input-definitions-to-object.ts'\nimport { replaceStringValue } from './utils/replace-string-value.ts'\nimport { turnCamelToKebabCasing } from './utils/turn-camel-to-kebab-casing.ts'\nimport { mergeObjects } from './utils/merge-objects.ts'\n\nconst widgetCache = new Map()\nconst tempCache = new Map()\n\ninterface parseOptions {\n prod?: boolean\n fetchWidget: (id: string) => Promise<Widget | null>\n fetchTemplate: (id: string) => Promise<Template | null>\n}\n\nconst defaultOptions: parseOptions = {\n fetchWidget: async () => null,\n fetchTemplate: async () => null,\n prod: false,\n}\n\nexport const parseTemplate = async (\n temp: Template,\n opt: parseOptions = defaultOptions\n) => {\n tempCache.set(temp.id, temp)\n\n if (temp.extends) {\n const base =\n tempCache.get(temp.extends) ||\n (await opt.fetchTemplate(temp.extends))\n\n if (!base) {\n throw new Error(`Template \"${temp.extends}\" not found`)\n }\n\n tempCache.set(temp.extends, base)\n temp = mergeObjects(base, temp) as Template\n }\n\n const {\n metadata = {},\n scripts = [],\n stylesheets = [],\n links = [],\n fonts = [],\n favicons = [],\n content = '',\n manifest,\n ...data\n } = temp ?? {}\n\n const widgetStyles = new Map()\n\n const bodyContent =\n typeof content === 'string'\n ? content\n : await parseContent(\n content as TemplateContent,\n data,\n widgetStyles,\n opt\n )\n\n if (!metadata['charset']) {\n metadata['charset'] = 'UTF-8'\n }\n\n if (!metadata['viewport']) {\n metadata['viewport'] = 'width=device-width, initial-scale=1.0'\n }\n\n const metas = Object.entries(metadata)\n .map(([key, value]) => {\n if (key.startsWith('property:')) {\n return `<meta property=\"${key.replace('property:', '')}\" content=\"${value}\">`\n }\n\n return `<meta name=\"${key}\" content=\"${value}\">`\n })\n .join('')\n\n let ls = ''\n\n links.forEach((link) => {\n let l = '<link '\n\n Object.entries(link).forEach(([key, value]) => {\n l += `${key}=\"${value}\" `\n })\n\n ls += l + '/>'\n })\n\n let fi = ''\n\n favicons.forEach((link) => {\n let l = '<link '\n\n Object.entries(link).forEach(([key, value]) => {\n l += `${key}=\"${key === 'href' ? './assets/favicons/' : ''}${value}\" `\n })\n\n fi += l + '/>'\n })\n\n let ft = ''\n\n fonts.forEach((font) => {\n ft += `<link rel=\"preload\" href=\"./assets/fonts/${font}\" as=\"font\" crossorigin=\"anonymous\">`\n })\n\n let st = ''\n\n ;[...stylesheets, ...Array.from(widgetStyles.entries())].forEach(\n (stylesheet) => {\n if (typeof stylesheet === 'string') {\n if (stylesheet.startsWith('http')) {\n st += `<link rel=\"stylesheet\" href=\"${stylesheet}\" >`\n } else if (stylesheet.endsWith('.css')) {\n st += `<link rel=\"stylesheet\" href=\"./stylesheets/${stylesheet}\">`\n } else {\n st += `<style>${stylesheet}</style>`\n }\n } else if (Array.isArray(stylesheet)) {\n const [id, style] = stylesheet\n st += `<style id=\"${id}\">${parseStyle(style)}</style>`\n } else {\n st += `<style`\n\n Object.entries(stylesheet.attributes).forEach(\n ([key, value]) => {\n st += `${key}=\"${value}\" `\n }\n )\n\n st += '></style>'\n }\n }\n )\n\n let sc = ''\n\n scripts.forEach((script) => {\n if (typeof script === 'string') {\n if (script.startsWith('http')) {\n sc += `<script src=\"${script}\"></script>`\n } else if (script.endsWith('.js')) {\n sc += `<script src=\"./scripts/${script}\"></script>`\n } else {\n sc += `<script>${script}</script>`\n }\n } else {\n sc += '<script '\n\n Object.entries(script).forEach(([key, value]) => {\n sc += `${key}=\"${value}\" `\n })\n\n sc += `></script>`\n }\n })\n\n return `<!doctype html>\n<html lang=\"${data.lang ?? 'en'}\">\n<head>\n <title>${data.title}</title>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <!-- og -->\n <meta property=\"og:title\" content=\"${data.title}\">\n <meta property=\"og:type\" content=\"website\">\n <meta property=\"og:description\" content=\"${data.description}\">\n <meta property=\"og:image\" content=\"${data.image}\">\n <meta property=\"og:url\" content=\"${data.domain}\">\n <meta property=\"og:site_name\" content=\"${data.title}\">\n ${metas ? `<!-- metas -->${metas}` : ''}\n ${fi ? `<!-- favicons -->${fi}` : ''}\n ${ft ? `<!-- fonts -->${ft}` : ''}\n ${ls ? `<!-- links -->${ls}` : ''}\n ${manifest ? `<link rel=\"manifest\" href=\"./assets/${manifest}\">` : ''}\n ${st ? `<!-- stylesheets -->${st}` : ''}\n</head>\n<body>\n${bodyContent}\n${sc ? '<!-- scripts -->' + sc : ''}\n</body>\n</html>`\n .replace(/\\s{2,}/g, ' ')\n .replace(/[\\t\\n]+/g, '')\n}\n\nfunction parseStyle(style: Style): string {\n if (typeof style === 'string') {\n return style\n }\n\n return Object.entries(style)\n .map(([key, value]) => {\n if (typeof value === 'object') {\n return `${turnCamelToKebabCasing(key)} { ${parseStyle(value)} }`\n }\n\n return `${turnCamelToKebabCasing(key)}: ${value};`\n })\n .join(' ')\n}\n\nasync function parseContent(\n content: TemplateContent,\n data = {},\n widgetStyles: Map<string, Style>,\n opt: parseOptions = defaultOptions\n): Promise<string> {\n return (\n await Promise.all(\n content.map(async (node) => {\n if (typeof node === 'string') {\n return replaceStringValue(node, data)\n }\n\n let { name, children, ...attributes } = node\n\n if (name === 'widget') {\n node['data-render-id'] =\n node['data-render-id'] ||\n Math.random().toString(36).substring(2, 15)\n ;({ name, children, ...attributes } = node)\n\n if (attributes.id) {\n const widget =\n widgetCache.get(attributes.id) ||\n (await opt.fetchWidget(attributes.id))\n\n if (widget) {\n if (typeof widget.render === 'function') {\n children = [\n widget.render({\n ...inputDefinitionsToObject(\n widget.inputs\n ),\n ...attributes,\n env: data,\n }),\n ]\n } else {\n children = widget.content\n ? [widget.content]\n : []\n }\n\n if (widget.style) {\n widgetStyles.set(attributes.id, widget.style)\n }\n\n widgetCache.set(attributes.id, widget)\n }\n }\n\n if (opt.prod) {\n return children.join('')\n }\n }\n\n const attrs = Object.entries(attributes)\n .map(([name, value]) => {\n if (typeof value === 'string') {\n value = replaceStringValue(value, data)\n }\n\n return `${name}=\"${value}\"`\n })\n .join(' ')\n\n return (\n `<${name}` +\n (attrs ? ` ${attrs}` : '') +\n `>${await parseContent(children, data, widgetStyles, opt)}</${name}>`\n )\n })\n )\n ).join('')\n}\n", "import { parseTemplate } from './parse-template.js'\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nif (window) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n window.BFS = {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n ...(window.BFS || {}),\n SITE_BUILDER: {\n parseTemplate,\n },\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["inputDefinitionsToObject", "inputDefinitions", "acc", "name", "value", "type", "definitions", "__name", "deepValue", "__name", "obj", "key", "acc", "k", "replaceStringValue", "__name", "value", "data", "match", "full", "key", "dv", "deepValue", "turnCamelToKebabCasing", "__name", "str", "match", "i", "mergeObjects", "a", "b", "obj", "key", "__name", "widgetCache", "tempCache", "defaultOptions", "parseTemplate", "__name", "temp", "opt", "base", "mergeObjects", "metadata", "scripts", "stylesheets", "links", "fonts", "favicons", "content", "manifest", "data", "widgetStyles", "bodyContent", "parseContent", "metas", "key", "value", "ls", "link", "l", "fi", "ft", "font", "st", "stylesheet", "id", "style", "parseStyle", "sc", "script", "turnCamelToKebabCasing", "node", "replaceStringValue", "name", "children", "attributes", "widget", "inputDefinitionsToObject", "attrs", "parseTemplate"]
7
+ }
@@ -0,0 +1 @@
1
+ export*from"./types.js";export*from"./parse-template.js";
@@ -0,0 +1,25 @@
1
+ var P=Object.defineProperty;var g=(e,s)=>P(e,"name",{value:s,configurable:!0});import{inputDefinitionsToObject as v}from"./utils/input-definitions-to-object.js";import{replaceStringValue as E}from"./utils/replace-string-value.js";import{turnCamelToKebabCasing as W}from"./utils/turn-camel-to-kebab-casing.js";import{mergeObjects as A}from"./utils/merge-objects.js";const C=new Map,j=new Map,x={fetchWidget:async()=>null,fetchTemplate:async()=>null,prod:!1},H=g(async(e,s=x)=>{if(j.set(e.id,e),e.extends){const t=j.get(e.extends)||await s.fetchTemplate(e.extends);if(!t)throw new Error(`Template "${e.extends}" not found`);j.set(e.extends,t),e=A(t,e)}const{metadata:o={},scripts:h=[],stylesheets:p=[],links:m=[],fonts:$=[],favicons:a=[],content:d="",manifest:n,...i}=e??{},T=new Map,k=typeof d=="string"?d:await M(d,i,T,s);o.charset||(o.charset="UTF-8"),o.viewport||(o.viewport="width=device-width, initial-scale=1.0");const O=Object.entries(o).map(([t,r])=>t.startsWith("property:")?`<meta property="${t.replace("property:","")}" content="${r}">`:`<meta name="${t}" content="${r}">`).join("");let y="";m.forEach(t=>{let r="<link ";Object.entries(t).forEach(([c,w])=>{r+=`${c}="${w}" `}),y+=r+"/>"});let u="";a.forEach(t=>{let r="<link ";Object.entries(t).forEach(([c,w])=>{r+=`${c}="${c==="href"?"./assets/favicons/":""}${w}" `}),u+=r+"/>"});let b="";$.forEach(t=>{b+=`<link rel="preload" href="./assets/fonts/${t}" as="font" crossorigin="anonymous">`});let l="";[...p,...Array.from(T.entries())].forEach(t=>{if(typeof t=="string")t.startsWith("http")?l+=`<link rel="stylesheet" href="${t}" >`:t.endsWith(".css")?l+=`<link rel="stylesheet" href="./stylesheets/${t}">`:l+=`<style>${t}</style>`;else if(Array.isArray(t)){const[r,c]=t;l+=`<style id="${r}">${S(c)}</style>`}else l+="<style",Object.entries(t.attributes).forEach(([r,c])=>{l+=`${r}="${c}" `}),l+="></style>"});let f="";return h.forEach(t=>{typeof t=="string"?t.startsWith("http")?f+=`<script src="${t}"></script>`:t.endsWith(".js")?f+=`<script src="./scripts/${t}"></script>`:f+=`<script>${t}</script>`:(f+="<script ",Object.entries(t).forEach(([r,c])=>{f+=`${r}="${c}" `}),f+="></script>")}),`<!doctype html>
2
+ <html lang="${i.lang??"en"}">
3
+ <head>
4
+ <title>${i.title}</title>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <!-- og -->
8
+ <meta property="og:title" content="${i.title}">
9
+ <meta property="og:type" content="website">
10
+ <meta property="og:description" content="${i.description}">
11
+ <meta property="og:image" content="${i.image}">
12
+ <meta property="og:url" content="${i.domain}">
13
+ <meta property="og:site_name" content="${i.title}">
14
+ ${O?`<!-- metas -->${O}`:""}
15
+ ${u?`<!-- favicons -->${u}`:""}
16
+ ${b?`<!-- fonts -->${b}`:""}
17
+ ${y?`<!-- links -->${y}`:""}
18
+ ${n?`<link rel="manifest" href="./assets/${n}">`:""}
19
+ ${l?`<!-- stylesheets -->${l}`:""}
20
+ </head>
21
+ <body>
22
+ ${k}
23
+ ${f?"<!-- scripts -->"+f:""}
24
+ </body>
25
+ </html>`.replace(/\s{2,}/g," ").replace(/[\t\n]+/g,"")},"parseTemplate");function S(e){return typeof e=="string"?e:Object.entries(e).map(([s,o])=>typeof o=="object"?`${W(s)} { ${S(o)} }`:`${W(s)}: ${o};`).join(" ")}g(S,"parseStyle");async function M(e,s={},o,h=x){return(await Promise.all(e.map(async p=>{if(typeof p=="string")return E(p,s);let{name:m,children:$,...a}=p;if(m==="widget"){if(p["data-render-id"]=p["data-render-id"]||Math.random().toString(36).substring(2,15),{name:m,children:$,...a}=p,a.id){const n=C.get(a.id)||await h.fetchWidget(a.id);n&&(typeof n.render=="function"?$=[n.render({...v(n.inputs),...a,env:s})]:$=n.content?[n.content]:[],n.style&&o.set(a.id,n.style),C.set(a.id,n))}if(h.prod)return $.join("")}const d=Object.entries(a).map(([n,i])=>(typeof i=="string"&&(i=E(i,s)),`${n}="${i}"`)).join(" ");return`<${m}`+(d?` ${d}`:"")+`>${await M($,s,o,h)}</${m}>`}))).join("")}g(M,"parseContent");export{H as parseTemplate};
File without changes
@@ -0,0 +1 @@
1
+ var u=Object.defineProperty;var n=(e,t)=>u(e,"name",{value:t,configurable:!0});const c=n((e,t)=>String(t??"").split(".").filter(Boolean).reduce((r,o)=>{try{return r&&typeof r=="object"?r[o]:void 0}catch{return null}},e),"deepValue");export{c as deepValue};
@@ -0,0 +1 @@
1
+ var f=Object.defineProperty;var n=(e,t)=>f(e,"name",{value:t,configurable:!0});function p(e){return e.reduce((t,{name:i,value:r,type:o,definitions:u=[]})=>{switch(o){case"group":t[i]=p(u);break;default:t[i]=r}return t},{})}n(p,"inputDefinitionsToObject");export{p as inputDefinitionsToObject};
@@ -0,0 +1 @@
1
+ var o=Object.defineProperty;var y=(e,r)=>o(e,"name",{value:r,configurable:!0});function i(e,r){if(e===null||typeof e!="object"||r===null||typeof r!="object")return r;if(Array.isArray(e)&&Array.isArray(r))return Array.from(new Set([...e,...r]));const t=Array.isArray(e)?[...e]:{...e};for(const n in r)r.hasOwnProperty(n)&&(Array.isArray(e[n])&&Array.isArray(r[n])?t[n]=Array.from(new Set([...e[n],...r[n]])):t[n]=i(t[n],r[n]));return t}y(i,"mergeObjects");export{i as mergeObjects};
@@ -0,0 +1 @@
1
+ var i=Object.defineProperty;var t=(e,n)=>i(e,"name",{value:n,configurable:!0});import{deepValue as g}from"./deep-value.js";const m=t((e,n)=>{let r=null;for(;(r=/{{([a-z0-9.$_]+)}}/gim.exec(e))!==null;){const[l,c]=r,o=g(n,c);e=e.replace(l,String(o))}return e},"replaceStringValue");export{m as replaceStringValue};
@@ -0,0 +1 @@
1
+ var r=Object.defineProperty;var a=(n,t)=>r(n,"name",{value:t,configurable:!0});const i=a(n=>{const t=n.match(/(?:[A-Z]+(?=[A-Z][a-z])|[A-Z]+|[a-zA-Z])[^A-Z]*/g);if(t){for(let e=0;e<t.length;e++)t[e]=t[e].toLowerCase();return t.join("-")}return name},"turnCamelToKebabCasing");export{i as turnCamelToKebabCasing};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from './types.ts';
2
+ export * from './parse-template.ts';
@@ -0,0 +1,8 @@
1
+ import { Template, Widget } from './types.ts';
2
+ interface parseOptions {
3
+ prod?: boolean;
4
+ fetchWidget: (id: string) => Promise<Widget | null>;
5
+ fetchTemplate: (id: string) => Promise<Template | null>;
6
+ }
7
+ export declare const parseTemplate: (temp: Template, opt?: parseOptions) => Promise<string>;
8
+ export {};
@@ -0,0 +1,54 @@
1
+ export interface ObjectLiteral {
2
+ [key: string]: string | number | boolean | ObjectLiteral | ObjectLiteral[] | unknown;
3
+ }
4
+ interface StyleObject {
5
+ key: string | StyleObject;
6
+ }
7
+ export type Style = string | StyleObject;
8
+ interface TemplateContentNode {
9
+ [key: string]: string | number | boolean | TemplateContentNode[];
10
+ name: string;
11
+ children: TemplateContentNode[];
12
+ id: string;
13
+ }
14
+ export type TemplateContent = (string | TemplateContentNode)[];
15
+ export interface InputDefinition {
16
+ name: string;
17
+ value: unknown;
18
+ type: string;
19
+ label?: string;
20
+ description?: string;
21
+ definitions?: InputDefinition[];
22
+ options?: {
23
+ label: string;
24
+ value: unknown;
25
+ }[];
26
+ }
27
+ export interface Template {
28
+ id: string;
29
+ extends: string;
30
+ lang: string;
31
+ title: string;
32
+ domain: string;
33
+ description: string;
34
+ image?: string;
35
+ metadata?: Record<string, string>;
36
+ scripts?: string[];
37
+ stylesheets?: Array<string | string[] | ({
38
+ [key: string]: string;
39
+ } & {
40
+ attributes: Record<string, string>;
41
+ })>;
42
+ links?: Record<string, string>[];
43
+ fonts?: string[];
44
+ favicons?: Record<string, string>[];
45
+ manifest?: string;
46
+ content?: TemplateContent | string;
47
+ }
48
+ export interface Widget {
49
+ style: Style;
50
+ inputs: InputDefinition[];
51
+ render: <P>(props: P) => string;
52
+ content: string;
53
+ }
54
+ export {};
@@ -0,0 +1,2 @@
1
+ import { ObjectLiteral } from '../types.ts';
2
+ export declare const deepValue: (obj: ObjectLiteral | unknown[], key: string) => unknown;
@@ -0,0 +1,2 @@
1
+ import { ObjectLiteral, InputDefinition } from '../types.ts';
2
+ export declare function inputDefinitionsToObject(inputDefinitions: InputDefinition[]): ObjectLiteral;
@@ -0,0 +1 @@
1
+ export declare function mergeObjects(a: unknown, b: unknown): unknown;
@@ -0,0 +1 @@
1
+ export declare const replaceStringValue: (value: string, data: Record<string, unknown>) => string;
@@ -0,0 +1 @@
1
+ export declare const turnCamelToKebabCasing: (str: string) => string | void;
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "@beforesemicolon/site-builder",
3
+ "version": "0.1.0",
4
+ "description": "Site builder based on JSON files",
5
+ "engines": {
6
+ "node": ">=18.16.0"
7
+ },
8
+ "type": "module",
9
+ "types": "./dist/types/index.d.ts",
10
+ "exports": {
11
+ "import": "./dist/esm/index.js",
12
+ "require": "./dist/cjs/index.js",
13
+ "default": "./dist/cjs/index.js",
14
+ "types": "./dist/types/index.d.ts"
15
+ },
16
+ "scripts": {
17
+ "test": "jest --coverage",
18
+ "test:watch": "jest --watch",
19
+ "docs:watch": "rm -rf website && NODE_ENV=development nodemon --watch docs -e js,css,md,json --exec 'node node_modules/@beforesemicolon/builder/dist/esm/docs/run.js'",
20
+ "local": "nodemon --watch src -e ts --exec 'npm run build && npm pack && npm link'",
21
+ "build:browser": "node node_modules/@beforesemicolon/builder/dist/esm/build-browser.js",
22
+ "build:modules": "node node_modules/@beforesemicolon/builder/dist/esm/build-modules.js",
23
+ "build": "rm -rf dist && npm-run-all lint test && tsc --emitDeclarationOnly && npm-run-all build:modules build:browser",
24
+ "lint": "eslint ./src && prettier --check .",
25
+ "format": "eslint ./src --fix && prettier --write ."
26
+ },
27
+ "author": "Elson Correia",
28
+ "license": "BSD-3-Clause",
29
+ "repository": {
30
+ "url": "https://github.com/beforesemicolon/markup",
31
+ "type": "git"
32
+ },
33
+ "keywords": [
34
+ "html",
35
+ "templating system",
36
+ "template literal",
37
+ "markup"
38
+ ],
39
+ "funding": {
40
+ "url": "https://github.com/sponsors/beforesemicolon",
41
+ "type": "github"
42
+ },
43
+ "devDependencies": {
44
+ "@beforesemicolon/builder": "^1.4.0",
45
+ "@gjsify/esbuild-plugin-transform-ext": "0.0.4",
46
+ "@types/jest": "^29.5.11",
47
+ "@types/jsdom": "^21.1.6",
48
+ "@types/jsdom-global": "^3.0.7",
49
+ "@types/node": "^20.10.5",
50
+ "@types/node-sass": "^4.11.7",
51
+ "@typescript-eslint/eslint-plugin": "^6.15.0",
52
+ "@typescript-eslint/parser": "^6.15.0",
53
+ "core-js": "^3.34.0",
54
+ "esbuild": "^0.25.0",
55
+ "esbuild-plugin-text-replace": "^1.3.0",
56
+ "eslint": "^8.56.0",
57
+ "eslint-config-prettier": "^9.1.0",
58
+ "eslint-config-standard": "^17.1.0",
59
+ "eslint-plugin-import": "^2.29.1",
60
+ "eslint-plugin-n": "^16.5.0",
61
+ "eslint-plugin-prettier": "^5.1.2",
62
+ "eslint-plugin-promise": "^6.1.1",
63
+ "front-matter": "^4.0.2",
64
+ "global-jsdom": "^9.2.0",
65
+ "highlight.js": "^11.10.0",
66
+ "install": "^0.13.0",
67
+ "isomorphic-dompurify": "^2.16.0",
68
+ "jest": "^29.7.0",
69
+ "jest-environment-jsdom": "^29.7.0",
70
+ "jsdom": "^25.0.1",
71
+ "marked": "^14.1.2",
72
+ "marked-highlight": "^2.1.4",
73
+ "nodemon": "^3.1.7",
74
+ "npm-run-all": "^4.1.5",
75
+ "prettier": "3.3.3",
76
+ "tinybench": "^3.0.0",
77
+ "ts-jest": "^29.1.1",
78
+ "tsx": "^4.7.0",
79
+ "typescript": "^5.3.3"
80
+ }
81
+ }