@beforesemicolon/site-builder 0.32.0 → 0.34.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.
@@ -0,0 +1,28 @@
1
+ plugins = []
2
+ headers = []
3
+ redirects = []
4
+
5
+ [functions]
6
+
7
+ [functions."*"]
8
+
9
+ [build]
10
+ publish = "/Users/ecorreia/Sites/@beforesemicolon/site-builder/public"
11
+ publishOrigin = "ui"
12
+ commandOrigin = "ui"
13
+ base = "/Users/ecorreia/Sites/@beforesemicolon/site-builder"
14
+ command = "npm run build"
15
+
16
+ [build.environment]
17
+
18
+ [build.processing]
19
+
20
+ [build.processing.css]
21
+
22
+ [build.processing.html]
23
+
24
+ [build.processing.images]
25
+
26
+ [build.processing.js]
27
+
28
+ [build.services]
package/README.md CHANGED
@@ -1,133 +1,447 @@
1
- # Markup
1
+ # 🚀 BeforeSemicolon Site Builder
2
2
 
3
- Reactive HTML Templating System
3
+ [![npm version](https://badge.fury.io/js/%40beforesemicolon%2Fsite-builder.svg)](https://badge.fury.io/js/%40beforesemicolon%2Fsite-builder)
4
+ [![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
5
+ [![Build Status](https://github.com/beforesemicolon/site-builder/workflows/CI/badge.svg)](https://github.com/beforesemicolon/site-builder/actions)
4
6
 
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)
7
+ ## The Next-Generation Website Builder for Developers
10
8
 
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.
9
+ **BeforeSemicolon Site Builder** is a revolutionary JSON-based static site generator that puts developers in complete control. Unlike traditional website builders that lock you into proprietary systems, our builder gives you the power of code with the simplicity of configuration.
12
10
 
13
- It consists of 3 main APIs with additional utilities to simplify things even further:
11
+ ### 🎯 Why Choose BeforeSemicolon Site Builder?
14
12
 
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;
13
+ **🆚 Traditional Website Builders vs. BeforeSemicolon**
18
14
 
19
- ### Motivation
15
+ | Feature | Traditional Builders | BeforeSemicolon Site Builder |
16
+ | ------------------------ | ----------------------- | ---------------------------- |
17
+ | **Data Format** | Proprietary/Database | Standard JSON files |
18
+ | **Version Control** | ❌ Limited/None | ✅ Full Git integration |
19
+ | **Customization** | ❌ Template limitations | ✅ Unlimited flexibility |
20
+ | **Performance** | ❌ Bloated output | ✅ Optimized static files |
21
+ | **Portability** | ❌ Platform locked | ✅ Framework agnostic |
22
+ | **Developer Experience** | ❌ GUI only | ✅ Code + Visual |
23
+ | **SEO Control** | ❌ Limited | ✅ Complete control |
24
+ | **Build Pipeline** | ❌ No control | ✅ Custom build process |
20
25
 
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.
26
+ ## 🌟 Key Features
22
27
 
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.
28
+ ### 📄 **JSON-First Architecture**
24
29
 
25
- From this:
30
+ Define your entire website structure using simple, readable JSON files. No proprietary formats, no vendor lock-in. Templates, widgets, and components are all described in JSON, supporting inheritance, metadata, localization, and more.
26
31
 
27
- ```javascript
28
- let count = 0
32
+ ### 🧩 **Dynamic Widget System**
29
33
 
30
- // tedious DOM definition and manipulation
31
- const p = document.createElement('p')
32
- p.textContent = `count: ${count}`
34
+ Create reusable, interactive components with state management and custom logic. Widgets can be defined with inputs, state, and a render function or static content. Widgets support localization, environment variables, and can compose other components.
33
35
 
34
- const btn = document.createElement('button')
35
- btn.type = 'button'
36
- btn.textContent = 'count up'
36
+ ### 🏗️ **Template Inheritance & Metadata**
37
37
 
38
- // limiting event driven
39
- btn.addEventListener('onclick', () => {
40
- count += 1
41
- p.textContent = `count: ${count}`
38
+ Templates can extend other templates, allowing for DRY and maintainable site structures. Each template supports rich metadata (SEO, social, custom), scripts, stylesheets, links, fonts, favicons, manifest, CSP, preload, and structured data.
42
39
 
43
- if (count > 10) {
44
- alert('You counted passed 10!')
45
- }
40
+ ### 🗂️ **Component Library**
41
+
42
+ Build a library of reusable UI components, each with their own styles and content. Components can be referenced and rendered inside widgets and templates.
43
+
44
+ ### 🌍 **Localization Support**
45
+
46
+ Localization files (JSON) are automatically loaded and flattened for use in templates and widgets, enabling multi-language sites out of the box.
47
+
48
+ ### ⚡ **Lightning-Fast Build Process**
49
+
50
+ The build script processes templates, widgets, components, assets, and localization files, outputting a fully static, minified site. HTML and CSS are minified, and assets/data are copied to the output directory. Supports production and development modes.
51
+
52
+ ### 🛠️ **Highly Configurable & Extensible**
53
+
54
+ Custom fetchers for widgets/templates, custom components, asset origins, and more. Caching and environment options are available for advanced use cases.
55
+
56
+ ### 🧑‍💻 **TypeScript Native**
57
+
58
+ Strong TypeScript types for templates, widgets, components, styles, and scripts. Input definitions support a wide range of types (text, html, markdown, media, options, groups, lists, etc.).
59
+
60
+ ## 🚀 Quick Start
61
+
62
+ ### Installation
63
+
64
+ ```bash
65
+ npm install @beforesemicolon/site-builder
66
+ ```
67
+
68
+ ### Basic Usage
69
+
70
+ ```typescript
71
+ import { buildTemplates, parseTemplate } from '@beforesemicolon/site-builder'
72
+
73
+ // Build entire site
74
+ await buildTemplates({
75
+ srcDir: './src',
76
+ publicDir: './dist',
77
+ prod: true,
46
78
  })
47
79
 
48
- document.body.append(p, btn)
80
+ // Parse individual template
81
+ const template = {
82
+ id: 'home',
83
+ name: 'Home Page',
84
+ route: '/',
85
+ type: 'page',
86
+ title: 'Welcome to My Site',
87
+ description: 'An amazing website built with BeforeSemicolon',
88
+ content: [
89
+ {
90
+ name: 'h1',
91
+ children: ['Welcome to {{title}}'],
92
+ },
93
+ ],
94
+ }
95
+
96
+ const html = await parseTemplate(template)
49
97
  ```
50
98
 
51
- To this:
99
+ ## 📁 Project Structure
100
+
101
+ ```
102
+ my-website/
103
+ ├── src/
104
+ │ ├── templates/ # Page templates (JSON)
105
+ │ │ ├── home.json
106
+ │ │ ├── about.json
107
+ │ │ └── base.json
108
+ │ ├── widgets/ # Dynamic widgets (JS)
109
+ │ │ ├── navigation.js
110
+ │ │ └── contact-form.js
111
+ │ ├── components/ # Static components (JSON)
112
+ │ │ ├── hero.json
113
+ │ │ └── footer.json
114
+ │ ├── stylesheets/ # CSS or other stylesheet files
115
+ │ │ └── main.css
116
+ │ ├── scripts/ # JavaScript files for the site
117
+ │ │ └── app.js
118
+ │ ├── assets/ # Static asset/media files (fonts, icons, logo, favicons, etc.)
119
+ │ │ ├── fonts/
120
+ │ │ ├── icons/
121
+ │ │ ├── logo/
122
+ │ │ ├── videos/
123
+ │ │ ├── audios/
124
+ │ │ ├── images/
125
+ │ │ └── favicons/
126
+ │ │ └── manifest.json
127
+ │ │ └── _redirects
128
+ │ │ └── robots.txt
129
+ │ │ └── sitemap.xml
130
+ │ ├── data/ # Static data files (JSON, CSV, etc.)
131
+ │ │ └── products.json
132
+ │ └── locales/ # Localization files (e.g., en.json, fr.json)
133
+ │ ├── en.json
134
+ │ └── fr.json
135
+ └── public/ # Generated site
136
+ ```
137
+
138
+ ## 📝 Templates
139
+
140
+ Templates are the backbone of your site. They define page structure, metadata, and content.
141
+
142
+ ### Base Template
143
+
144
+ ```json
145
+ {
146
+ "id": "home",
147
+ "name": "Home Page",
148
+ "route": "/",
149
+ "type": "base",
150
+ "lang": "en",
151
+ "title": "My Awesome Website",
152
+ "domain": "https://mysite.com",
153
+ "description": "A site built with BeforeSemicolon Site Builder",
154
+ "metadata": {
155
+ "keywords": ["website", "builder", "static"],
156
+ "themeColor": "#ffffff"
157
+ },
158
+ "stylesheets": ["main.css"],
159
+ "scripts": ["/app.js"],
160
+ "content": [
161
+ {
162
+ "name": "header",
163
+ "class": "site-header",
164
+ "children": [
165
+ {
166
+ "name": "h1",
167
+ "children": ["{{title}}"]
168
+ }
169
+ ]
170
+ }
171
+ ]
172
+ }
173
+ ```
174
+
175
+ ### Template Inheritance
176
+
177
+ ```json
178
+ {
179
+ "id": "about",
180
+ "extends": "base",
181
+ "type": "page",
182
+ "title": "About Us",
183
+ "route": "/about",
184
+ "content": [
185
+ {
186
+ "name": "main",
187
+ "children": [
188
+ {
189
+ "name": "h1",
190
+ "children": ["About {{title}}"]
191
+ }
192
+ ]
193
+ }
194
+ ]
195
+ }
196
+ ```
197
+
198
+ ## 🧩 Widgets
199
+
200
+ Widgets are dynamic, reusable components with logic and state.
52
201
 
53
202
  ```javascript
54
- // reactive data
55
- const [count, updateCount] = state(0)
203
+ // widgets/counter.js
204
+ export default {
205
+ id: 'counter',
206
+ name: 'Counter Widget',
207
+ inputs: [
208
+ {
209
+ type: 'number',
210
+ name: 'initialValue',
211
+ value: 0,
212
+ label: 'Initial Value',
213
+ },
214
+ ],
215
+ render: ({ initialValue, env }) => {
216
+ return `
217
+ <div class="counter" data-initial="${initialValue}">
218
+ <button onclick="decrement()">-</button>
219
+ <span class="count">${initialValue}</span>
220
+ <button onclick="increment()">+</button>
221
+ </div>
222
+ `
223
+ },
224
+ scripts: ['widgets/counter-behavior.js'],
225
+ }
226
+ ```
56
227
 
57
- // data driven
58
- effect(() => {
59
- if (count() > 10) {
60
- alert('You counted passed 10!')
228
+ ### Using Widgets in Templates
229
+
230
+ ```json
231
+ {
232
+ "content": [
233
+ {
234
+ "name": "widget",
235
+ "id": "counter",
236
+ "initialValue": 10
237
+ }
238
+ ],
239
+ "widgetsData": {
240
+ "counter": {
241
+ "initialValue": 5,
242
+ "theme": "dark"
243
+ }
61
244
  }
62
- })
245
+ }
246
+ ```
63
247
 
64
- const countUp = () => {
65
- updateCount((prev) => prev + 1)
248
+ ## 🎨 Components
249
+
250
+ Components are static, reusable UI elements.
251
+
252
+ ```json
253
+ {
254
+ "id": "hero",
255
+ "stylesheets": ["components/hero.css"],
256
+ "content": [
257
+ {
258
+ "name": "section",
259
+ "class": "hero",
260
+ "children": [
261
+ {
262
+ "name": "h1",
263
+ "class": "hero-title",
264
+ "children": ["{{title}}"]
265
+ },
266
+ {
267
+ "name": "p",
268
+ "class": "hero-subtitle",
269
+ "children": ["{{subtitle}}"]
270
+ }
271
+ ]
272
+ }
273
+ ]
66
274
  }
275
+ ```
276
+
277
+ ## 🎯 Advanced Features
278
+
279
+ ### Dynamic Content Rendering
67
280
 
68
- // reactive DOM/templates
69
- html`
70
- <p>count: ${count}</p>
71
- <button type="button" onclick="${countUp}">count up</button>
72
- `.render(document.body)
281
+ ```typescript
282
+ import { parseWidget } from '@beforesemicolon/site-builder'
283
+
284
+ const dynamicContent = await parseWidget({
285
+ node: {
286
+ name: 'widget',
287
+ id: 'product-list',
288
+ category: 'electronics',
289
+ },
290
+ data: { products: await fetchProducts() },
291
+ })
73
292
  ```
74
293
 
75
- ### How does it work?
294
+ ### Custom Styling
76
295
 
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.
296
+ ```typescript
297
+ import { parseStyle } from '@beforesemicolon/site-builder'
78
298
 
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.
299
+ const styles = parseStyle({
300
+ '.hero': {
301
+ backgroundColor: '#333',
302
+ color: 'white',
303
+ padding: '2rem',
304
+ },
305
+ })
306
+ ```
81
307
 
82
- Literally everything else is how you know it to be in plain HTML, CSS and JavaScript.
308
+ ### Build Optimization
83
309
 
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.
310
+ ```typescript
311
+ await buildTemplates({
312
+ srcDir: './src',
313
+ publicDir: './dist',
314
+ prod: true, // Enables minification and optimization
315
+ })
316
+ ```
85
317
 
86
- #### Examples
318
+ ## 🔧 Configuration
87
319
 
88
- This is a simple example of a button, but you can check:
320
+ ### Parse Options
89
321
 
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)
322
+ ```typescript
323
+ const options = {
324
+ useCache: true,
325
+ prod: false,
326
+ assetsOrigin: 'https://cdn.mysite.com',
327
+ components: componentLibrary,
328
+ locales: localizationFiles,
329
+ fetchWidget: async (id) => await loadWidget(id),
330
+ fetchTemplate: async (id) => await loadTemplate(id),
331
+ }
93
332
 
94
- ## Install
333
+ const html = await parseTemplate(template, options)
334
+ ```
95
335
 
336
+ ### Input Definitions
337
+
338
+ Create rich form inputs for your widgets:
339
+
340
+ ```typescript
341
+ const inputs = [
342
+ {
343
+ type: 'text',
344
+ name: 'title',
345
+ label: 'Page Title',
346
+ value: 'Default Title',
347
+ },
348
+ {
349
+ type: 'options',
350
+ name: 'theme',
351
+ label: 'Color Theme',
352
+ definitions: [
353
+ { name: 'light', value: 'light' },
354
+ { name: 'dark', value: 'dark' },
355
+ ],
356
+ },
357
+ {
358
+ type: 'group',
359
+ name: 'seo',
360
+ label: 'SEO Settings',
361
+ definitions: [
362
+ { type: 'text', name: 'description' },
363
+ { type: 'image', name: 'ogImage' },
364
+ ],
365
+ },
366
+ ]
96
367
  ```
97
- npm install @beforesemicolon/markup
368
+
369
+ ## 🛠️ Development Workflow
370
+
371
+ ### Development Server
372
+
373
+ ```bash
374
+ npm run docs:watch # Start development server with hot reload
98
375
  ```
99
376
 
100
- or
377
+ ### Building for Production
101
378
 
379
+ ```bash
380
+ npm run build # Build optimized production bundle
381
+ npm run test # Run test suite
382
+ npm run lint # Check code quality
102
383
  ```
103
- yarn add @beforesemicolon/markup
384
+
385
+ ### Testing
386
+
387
+ ```bash
388
+ npm test # Run all tests
389
+ npm run test:watch # Watch mode for development
104
390
  ```
105
391
 
106
- ## Use directly in the Browser
392
+ ## 🌟 Use Cases
107
393
 
108
- This library requires no build or parsing. The CDN package is one digit killobyte in size, tiny!
394
+ ### 🏢 **Business Websites**
109
395
 
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>
396
+ Create professional business sites with dynamic contact forms, product catalogs, and CMS integration.
116
397
 
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
- ```
398
+ ### 📝 **Blogs & Content Sites**
399
+
400
+ Build SEO-optimized blogs with markdown support, tagging systems, and social sharing.
401
+
402
+ ### 🛍️ **E-commerce**
403
+
404
+ Develop fast, conversion-optimized online stores with dynamic product listings and checkout flows.
405
+
406
+ ### 📱 **Landing Pages**
407
+
408
+ Craft high-converting landing pages with A/B testing capabilities and analytics integration.
409
+
410
+ ### 🎨 **Portfolios**
411
+
412
+ Showcase your work with customizable galleries, case studies, and contact forms.
122
413
 
123
- ### Usage
414
+ ## 🚀 Performance Benefits
124
415
 
125
- ```html
126
- <div id="app"></div>
416
+ - **Static Generation**: Pre-rendered HTML for maximum speed
417
+ - **Code Splitting**: Automatic optimization of JavaScript bundles
418
+ - **Asset Optimization**: Minified CSS/JS and optimized images
419
+ - **SEO Ready**: Server-side rendering with complete meta control
420
+ - **CDN Friendly**: Deploy anywhere with zero configuration
127
421
 
128
- <script>
129
- const { html, state, effect } = BFS.MARKUP
422
+ ## 🤝 Contributing
130
423
 
131
- html`<h1>Hello World</h1>`.render(document.getElementById('app'))
132
- </script>
424
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
425
+
426
+ ```bash
427
+ git clone https://github.com/beforesemicolon/site-builder.git
428
+ cd site-builder
429
+ npm install
430
+ npm run test
133
431
  ```
432
+
433
+ ## 📄 License
434
+
435
+ BSD-3-Clause License - see the [LICENSE](LICENSE) file for details.
436
+
437
+ ## 💝 Support
438
+
439
+ - ⭐ Star this repository
440
+ - 🐛 [Report issues](https://github.com/beforesemicolon/site-builder/issues)
441
+ - 💖 [Sponsor the project](https://github.com/sponsors/beforesemicolon)
442
+
443
+ ---
444
+
445
+ **Built with ❤️ by [BeforeSemicolon](https://beforesemicolon.com)**
446
+
447
+ _"The future of web development is declarative, portable, and developer-first."_
@@ -1 +1,11 @@
1
- "use strict";var z=Object.create;var u=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var I=Object.getPrototypeOf,K=Object.prototype.hasOwnProperty;var d=(t,s)=>u(t,"name",{value:s,configurable:!0});var L=(t,s)=>{for(var a in s)u(t,a,{get:s[a],enumerable:!0})},b=(t,s,a,p)=>{if(s&&typeof s=="object"||typeof s=="function")for(let m of H(s))!K.call(t,m)&&m!==a&&u(t,m,{get:()=>s[m],enumerable:!(p=G(s,m))||p.enumerable});return t};var h=(t,s,a)=>(a=t!=null?z(I(t)):{},b(s||!t||!t.__esModule?u(a,"default",{value:t,enumerable:!0}):a,t)),M=t=>b(u({},"__esModule",{value:!0}),t);var Y={};L(Y,{buildTemplates:()=>X});module.exports=M(Y);var i=h(require("path"),1),y=h(require("fs"),1),x=h(require("esbuild"),1),N=require("./utils/merge-objects.js"),P=require("./parse-template.js"),B=h(require("clean-css"),1),J=require("./types.js"),k=require("html-minifier");const Q=new B.default,{writeFile:F,readFile:v,readdir:O,mkdir:w,cp:U,rm:V}=y.default.promises,X=d(async({publicDir:t,srcDir:s,prod:a=!0})=>{const p=i.default.resolve(t,"scripts"),m=i.default.resolve(t,"stylesheets"),E=i.default.resolve(t,"assets");y.default.existsSync(t)&&await V(t,{recursive:!0,force:!0}),await w(t,{recursive:!0}),await w(p,{recursive:!0}),await w(m,{recursive:!0}),await U(i.default.resolve(s,"assets"),E,{recursive:!0});const R=await O(i.default.resolve(s,"templates")),S=await Promise.all(R.filter(e=>e.endsWith(".json")).map(async e=>{const n=i.default.basename(e);return{dir:i.default.dirname(e),name:n.replace(".json",""),content:JSON.parse(await v(i.default.resolve(s,"templates",e),"utf8"))}})),j=S.reduce((e,n)=>({...e,[n.name]:n}),{}),$=S.filter(({content:e})=>e.type===J.TemplateType.Page),g=i.default.resolve(s,"components");let T={};if(y.default.existsSync(g)){const e=await O(g),n=await Promise.all(e.filter(c=>c.endsWith(".json")).map(async c=>{const r=JSON.parse(await v(i.default.join(g,c),"utf8"));return[r.id,r]}));T=Object.fromEntries(n)}const C=d(async e=>{let n=typeof e=="string"?e:"";e&&typeof e=="object"&&"src"in e&&(n=String(e.src)),!n.startsWith("http")&&n.endsWith(".js")&&await x.default.build({entryPoints:[i.default.resolve(s,"scripts",n)],minify:!0,outfile:i.default.join(p,n)})},"handleScript"),W=d(async e=>{let n=typeof e=="string"?e:"";if(e&&typeof e=="object"&&"href"in e&&(n=String(e.href)),!n.startsWith("http")&&n.endsWith(".css")){const c=await v(i.default.resolve(s,"stylesheets",n),"utf8");await F(i.default.join(m,n),Q.minify(c).styles,"utf-8")}},"handleStylesheet");for(const{name:e,dir:n,content:c}of $){let r=c;if(r.extends){const o=j[r.extends];r=(0,N.mergeObjects)(o.content,r)}await w(i.default.join(t,n),{recursive:!0});for(let o=0;o<(r.scripts?.length??0);o++)await C(r.scripts[o]);for(let o=0;o<(r.stylesheets?.length??0);o++)await W(r.stylesheets[o]);const A=await(0,P.parseTemplate)(r,{prod:a,components:T,fetchTemplate:o=>j[o].content,fetchWidget:async o=>{const f=(await import(i.default.resolve(s,"widgets",`${o}.js`))).default;for(let l=0;l<(f.scripts?.length??0);l++)await C(f.scripts[l]);for(let l=0;l<(f.stylesheets?.length??0);l++)await W(f.stylesheets[l]);return f}}),q=(0,k.minify)(A,{collapseWhitespace:!0,removeComments:!0,minifyCSS:!0,minifyJS:!0});await F(i.default.join(t,n,`${e}.html`),q)}},"buildTemplates");0&&(module.exports={buildTemplates});
1
+ "use strict";var oe=Object.create;var x=Object.defineProperty;var ie=Object.getOwnPropertyDescriptor;var ae=Object.getOwnPropertyNames;var re=Object.getPrototypeOf,ce=Object.prototype.hasOwnProperty;var b=(t,n)=>x(t,"name",{value:n,configurable:!0});var le=(t,n)=>{for(var i in n)x(t,i,{get:n[i],enumerable:!0})},z=(t,n,i,g)=>{if(n&&typeof n=="object"||typeof n=="function")for(let p of ae(n))!ce.call(t,p)&&p!==i&&x(t,p,{get:()=>n[p],enumerable:!(g=ie(n,p))||g.enumerable});return t};var N=(t,n,i)=>(i=t!=null?oe(re(t)):{},z(n||!t||!t.__esModule?x(i,"default",{value:t,enumerable:!0}):i,t)),me=t=>z(x({},"__esModule",{value:!0}),t);var we={};le(we,{buildTemplates:()=>ue});module.exports=me(we);var e=N(require("path"),1),m=N(require("fs"),1),H=N(require("esbuild"),1),M=require("./utils/merge-objects.js"),Q=require("./parse-template.js"),V=N(require("clean-css"),1),Y=require("./types.js"),Z=require("html-minifier"),D=require("./utils/flatten-object.js");const pe=new V.default,{writeFile:T,readFile:C,readdir:P,mkdir:j,cp:w,rm:fe}=m.default.promises;async function de(t,n){try{const i=e.default.resolve(t,"templates"),g=e.default.resolve(t,"widgets"),p=await P(i),y=[];let v=null;for(const c of p)if(c.endsWith(".json")){const f=e.default.join(i,c),F=await C(f,"utf-8"),d=JSON.parse(F);c==="base.json"?v=d:y.push({id:d.id,name:d.name||d.id,url:`/${d.id}.html`,template:c})}const O=await P(g),h=[];for(const c of O)if(c.endsWith(".js")){const f=e.default.basename(c,".js");h.push({id:f,name:f.charAt(0).toUpperCase()+f.slice(1).replace(/-/g," "),file:c})}const W={meta:v,pages:y,widgets:h},$=e.default.join(n,"config.json");await T($,JSON.stringify(W,null,2)),console.log("Generated config.json with",y.length,"pages and",h.length,"widgets")}catch(i){throw console.error("Error generating admin config:",i),i}}b(de,"generateAdminConfig");const ue=b(async({publicDir:t,srcDir:n,prod:i=!0})=>{console.log("Building templates:",{publicDir:t,srcDir:n,prod:i});const g=process.cwd(),p=e.default.join(g,"_redirects"),y=e.default.join(t,"_redirects"),v=e.default.resolve(t,"scripts"),O=e.default.resolve(t,"stylesheets"),h=e.default.resolve(n,"assets"),W=e.default.resolve(n,"admin"),$=e.default.resolve(n,"widgets"),c=e.default.resolve(t,"admin","widgets"),f=e.default.resolve(t,"assets"),F=e.default.resolve(n,"data"),d=e.default.resolve(t,"data"),B=e.default.resolve(n,"assets","robots.txt"),ee=e.default.join(t,"robots.txt"),E=e.default.resolve(n,"assets","sitemap.xml");if(m.default.existsSync(t)&&await fe(t,{recursive:!0,force:!0}),await j(t,{recursive:!0}),await j(v,{recursive:!0}),await j(O,{recursive:!0}),m.default.existsSync(p)&&await w(p,y),m.default.existsSync(h)&&await w(h,f,{recursive:!0}),m.default.existsSync(F)&&await w(F,d,{recursive:!0}),m.default.existsSync(W)){const s=e.default.resolve(t,"admin");await j(s,{recursive:!0}),await w(W,s,{recursive:!0}),await de(n,s),i||(await j(c,{recursive:!0}),await w($,c,{recursive:!0}))}const te=await P(e.default.resolve(n,"templates")),J=e.default.resolve(n,"locales"),k={};if(m.default.existsSync(J)){const s=await P(J);for(const o of s)if(o.endsWith(".json")){const l=JSON.parse(await C(e.default.join(J,o),"utf8")),r=e.default.basename(o,".json");k[r]=(0,D.flattenObject)(l)}}const L=await Promise.all(te.filter(s=>s.endsWith(".json")).map(async s=>{const o=e.default.basename(s);return{dir:e.default.dirname(s),name:o.replace(".json",""),content:JSON.parse(await C(e.default.resolve(n,"templates",s),"utf8"))}})),_=L.reduce((s,o)=>({...s,[o.name]:o}),{}),A=L.filter(({content:s})=>s.type===Y.TemplateType.Page&&s.excluded!==!0),R=e.default.resolve(n,"components");let G={};if(m.default.existsSync(R)){const s=await P(R),o=await Promise.all(s.filter(l=>l.endsWith(".json")).map(async l=>{const r=JSON.parse(await C(e.default.join(R,l),"utf8"));return[r.id,r]}));G=Object.fromEntries(o)}const I=b(async s=>{let o=typeof s=="string"?s:"";s&&typeof s=="object"&&"src"in s&&(o=String(s.src)),!o.startsWith("http")&&o.endsWith(".js")&&await H.default.build({entryPoints:[e.default.resolve(n,"scripts",o)],minify:!0,outfile:e.default.join(v,o)})},"handleScript"),K=b(async s=>{let o=typeof s=="string"?s:"";if(s&&typeof s=="object"&&"href"in s&&(o=String(s.href)),!o.startsWith("http")&&o.endsWith(".css")){const l=await C(e.default.resolve(n,"stylesheets",o),"utf8");await T(e.default.join(O,o),pe.minify(l).styles,"utf-8")}},"handleStylesheet"),X=[];for(const{name:s,dir:o,content:l}of A){let r=l;if(r.extends){const a=_[r.extends];r=(0,M.mergeObjects)(a.content,r)}const q=l.domain||"",U=l.route||"";if(U){const a=q?`${q.replace(/\/$/,"")}/${U.replace(/^\//,"")}`:`/${U.replace(/^\//,"")}`;X.push(a)}await j(e.default.join(t,o),{recursive:!0});for(let a=0;a<(r.scripts?.length??0);a++)await I(r.scripts[a]);for(let a=0;a<(r.stylesheets?.length??0);a++)await K(r.stylesheets[a]);const se=await(0,Q.parseTemplate)(r,{prod:i,components:G,locales:k,fetchTemplate:a=>_[a].content,fetchWidget:async a=>{const S=(await import(e.default.resolve($,`${a}.js`))).default;for(let u=0;u<(S.scripts?.length??0);u++)await I(S.scripts[u]);for(let u=0;u<(S.stylesheets?.length??0);u++)await K(S.stylesheets[u]);return S}}),ne=(0,Z.minify)(se,{collapseWhitespace:!0,removeComments:!0,minifyCSS:!0,minifyJS:!0});await T(e.default.join(t,o,`${s}.html`),ne)}if(m.default.existsSync(B))await w(B,e.default.join(t,"robots.txt"));else{const o=`User-agent: *
2
+ Disallow:
3
+ Sitemap: ${A[0]?.content.domain?`${A[0].content.domain.replace(/\/$/,"")}/sitemap.xml`:"/sitemap.xml"}
4
+ `;await T(ee,o,"utf-8")}if(m.default.existsSync(E))await w(E,e.default.join(t,"sitemap.xml"));else{const s=`<?xml version="1.0" encoding="UTF-8"?>
5
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
6
+ `+X.map(o=>` <url>
7
+ <loc>${o}</loc>
8
+ </url>`).join(`
9
+ `)+`
10
+ </urlset>
11
+ `;await T(e.default.join(t,"sitemap.xml"),s,"utf-8")}},"buildTemplates");0&&(module.exports={buildTemplates});
@@ -1 +1 @@
1
- "use strict";var p=Object.defineProperty;var o=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var r=(t,s)=>{for(var n in s)p(t,n,{get:s[n],enumerable:!0})},c=(t,s,n,a)=>{if(s&&typeof s=="object"||typeof s=="function")for(let e of i(s))!l.call(t,e)&&e!==n&&p(t,e,{get:()=>s[e],enumerable:!(a=o(s,e))||a.enumerable});return t};var f=t=>c(p({},"__esModule",{value:!0}),t);var d={};r(d,{defaultOptions:()=>O});module.exports=f(d);const O={fetchWidget:async()=>null,fetchTemplate:async()=>null,prod:!1,assetsOrigin:"/"};0&&(module.exports={defaultOptions});
1
+ "use strict";var o=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var r=(s,e)=>{for(var n in e)o(s,n,{get:e[n],enumerable:!0})},i=(s,e,n,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of l(e))!c.call(s,t)&&t!==n&&o(s,t,{get:()=>e[t],enumerable:!(a=p(e,t))||a.enumerable});return s};var f=s=>i(o({},"__esModule",{value:!0}),s);var m={};r(m,{defaultOptions:()=>u});module.exports=f(m);const u={fetchWidget:async()=>null,fetchTemplate:async()=>null,useCache:!0,locales:{},components:{},prod:!1,assetsOrigin:"/"};0&&(module.exports={defaultOptions});
@@ -1 +1 @@
1
- "use strict";var o=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var p=(e,t)=>o(e,"name",{value:t,configurable:!0});var h=(e,t)=>{for(var n in t)o(e,n,{get:t[n],enumerable:!0})},$=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of g(t))!C.call(e,r)&&r!==n&&o(e,r,{get:()=>t[r],enumerable:!(i=f(t,r))||i.enumerable});return e};var b=e=>$(o({},"__esModule",{value:!0}),e);var M={};h(M,{parseComponent:()=>y});module.exports=b(M);var l=require("./utils/replace-string-value.js"),u=require("./utils/attributes-to-string.js");const y=p((e,t={},n=new Map)=>{if(!e||!e.content)return"";const{content:i,stylesheets:r,id:s}=e;return r&&n.set(`comp-${s}`,r),m(i,t,n)},"parseComponent");function m(e,t={},n=new Map){return e?e.map(i=>{if(typeof i=="string")return(0,l.replaceStringValue)(i,t);const{name:r,children:s,...c}=i,a=(0,u.attributeToString)(c,t);return`<${r}`+(a?` ${a}`:"")+`>${m(s,t,n)}</${r}>`}).join(""):""}p(m,"parseContent");0&&(module.exports={parseComponent});
1
+ "use strict";var o=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var p=(e,t)=>o(e,"name",{value:t,configurable:!0});var h=(e,t)=>{for(var i in t)o(e,i,{get:t[i],enumerable:!0})},y=(e,t,i,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of g(t))!C.call(e,r)&&r!==i&&o(e,r,{get:()=>t[r],enumerable:!(n=u(t,r))||n.enumerable});return e};var $=e=>y(o({},"__esModule",{value:!0}),e);var M={};h(M,{parseComponent:()=>b});module.exports=$(M);var a=require("./utils/replace-string-value.js"),f=require("./utils/attributes-to-string.js");const b=p((e,t={},i=new Map)=>{if(!e||!e.content)return"";const{content:n="",stylesheets:r,id:s}=e;return r&&i.set(`comp-${s}`,r),typeof n=="string"?n?(0,a.replaceStringValue)(n,t):"":c(n,t,i)},"parseComponent");function c(e,t={},i=new Map){return e.map(n=>{if(typeof n=="string")return(0,a.replaceStringValue)(n,t);const{name:r,children:s=[],...l}=n,m=(0,f.attributeToString)(l,t);return`<${r}`+(m?` ${m}`:"")+`>${c(s,t,i)}</${r}>`}).join("")}p(c,"parseContent");0&&(module.exports={parseComponent});