@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 +28 -0
- package/README.md +133 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/parse-template.js +25 -0
- package/dist/cjs/types.js +1 -0
- package/dist/cjs/utils/deep-value.js +1 -0
- package/dist/cjs/utils/input-definitions-to-object.js +1 -0
- package/dist/cjs/utils/merge-objects.js +1 -0
- package/dist/cjs/utils/replace-string-value.js +1 -0
- package/dist/cjs/utils/turn-camel-to-kebab-casing.js +1 -0
- package/dist/client.js +26 -0
- package/dist/client.js.map +7 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/parse-template.js +25 -0
- package/dist/esm/types.js +0 -0
- package/dist/esm/utils/deep-value.js +1 -0
- package/dist/esm/utils/input-definitions-to-object.js +1 -0
- package/dist/esm/utils/merge-objects.js +1 -0
- package/dist/esm/utils/replace-string-value.js +1 -0
- package/dist/esm/utils/turn-camel-to-kebab-casing.js +1 -0
- package/dist/types/client.d.ts +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/parse-template.d.ts +8 -0
- package/dist/types/types.d.ts +54 -0
- package/dist/types/utils/deep-value.d.ts +2 -0
- package/dist/types/utils/input-definitions-to-object.d.ts +2 -0
- package/dist/types/utils/merge-objects.d.ts +1 -0
- package/dist/types/utils/replace-string-value.d.ts +1 -0
- package/dist/types/utils/turn-camel-to-kebab-casing.d.ts +1 -0
- package/package.json +81 -0
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
|
+
[](https://markup.beforesemicolon.com)
|
|
6
|
+
[](https://github.com/beforesemicolon/markup/blob/main/docs/index.md)
|
|
7
|
+
[](https://www.npmjs.com/package/@beforesemicolon/markup)
|
|
8
|
+

|
|
9
|
+
[](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,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 @@
|
|
|
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
|
+
}
|