@stacksjs/stx 0.0.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/README.md ADDED
@@ -0,0 +1,800 @@
1
+ ![Social Card of Bun Plugin blade](https://github.com/stacksjs/stx/blob/main/.github/art/cover.jpg)
2
+
3
+ [![npm version][npm-version-src]][npm-version-href]
4
+ [![GitHub Actions][github-actions-src]][github-actions-href]
5
+ [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
6
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
7
+ <!-- [![Codecov][codecov-src]][codecov-href] -->
8
+
9
+ # stx
10
+
11
+ A Blade-like template engine plugin for Bun, enabling simple and powerful templating with .stx files.
12
+
13
+ ## Features
14
+
15
+ - 🦋 Laravel Blade-like syntax
16
+ - 🚀 Fast and lightweight
17
+ - 📦 Zero config
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ bun add bun-plugin-stx
23
+ ```
24
+
25
+ ## Setup
26
+
27
+ Add the plugin to your `bunfig.toml`:
28
+
29
+ ```toml
30
+ preload = [ "bun-plugin-stx" ]
31
+
32
+ # or as a serve plugin
33
+ [serve.static]
34
+ plugins = [ "bun-plugin-stx" ]
35
+ ```
36
+
37
+ Or register the plugin in your build script:
38
+
39
+ ```ts
40
+ import { build } from 'bun'
41
+ import stxPlugin from 'bun-plugin-stx'
42
+
43
+ await build({
44
+ entrypoints: ['./src/index.ts', './templates/home.stx'],
45
+ outdir: './dist',
46
+ plugins: [stxPlugin],
47
+ })
48
+ ```
49
+
50
+ ## Usage with ESM
51
+
52
+ ### 1. Configure Bun to use the plugin
53
+
54
+ In your build script or Bun configuration:
55
+
56
+ ```js
57
+ // build.js
58
+ import { build } from 'bun'
59
+ import stxPlugin from 'bun-plugin-stx'
60
+
61
+ await build({
62
+ entrypoints: ['./src/index.ts', './templates/home.stx'],
63
+ outdir: './dist',
64
+ plugins: [stxPlugin],
65
+ })
66
+ ```
67
+
68
+ ### 2. Import and use .stx files directly
69
+
70
+ You can import .stx files directly in your ESM code:
71
+
72
+ ```js
73
+ // app.js
74
+ import homeTemplate from './templates/home.stx'
75
+
76
+ // Use the processed HTML content
77
+ document.body.innerHTML = homeTemplate
78
+ ```
79
+
80
+ ### 3. Use with Bun's server
81
+
82
+ You can serve .stx files directly with Bun's server:
83
+
84
+ ```js
85
+ // server.js
86
+ import { serve } from 'bun'
87
+ import homeTemplate from './home.stx'
88
+
89
+ serve({
90
+ port: 3000,
91
+ fetch(req) {
92
+ return new Response(homeTemplate, {
93
+ headers: { 'Content-Type': 'text/html' }
94
+ })
95
+ }
96
+ })
97
+ ```
98
+
99
+ Or use as route handlers:
100
+
101
+ ```js
102
+ import about from './about.stx'
103
+ // server.js
104
+ import home from './home.stx'
105
+
106
+ export default {
107
+ port: 3000,
108
+ routes: {
109
+ '/': home,
110
+ '/about': about
111
+ }
112
+ }
113
+ ```
114
+
115
+ ## STX Template Syntax
116
+
117
+ STX templates use a syntax inspired by Laravel Blade. Templates can contain HTML with special directives for rendering dynamic content.
118
+
119
+ ### Basic Example
120
+
121
+ ```html
122
+ <!DOCTYPE html>
123
+ <html>
124
+ <head>
125
+ <title>STX Example</title>
126
+ <script>
127
+ // Define your data as an ESM export
128
+ export const title = "Hello World";
129
+ export const items = ["Apple", "Banana", "Cherry"];
130
+ export const showFooter = true;
131
+ </script>
132
+ </head>
133
+ <body>
134
+ <h1>{{ title }}</h1>
135
+
136
+ <ul>
137
+ @foreach (items as item)
138
+ <li>{{ item }}</li>
139
+ @endforeach
140
+ </ul>
141
+
142
+ @if (showFooter)
143
+ <footer>Copyright 2023</footer>
144
+ @endif
145
+ </body>
146
+ </html>
147
+ ```
148
+
149
+ ### Data Export Options
150
+
151
+ There are two ways to expose data in your STX templates:
152
+
153
+ #### 1. ESM exports (recommended)
154
+
155
+ ```html
156
+ <script>
157
+ // Modern ESM named exports
158
+ export const title = "Hello World";
159
+ export const count = 42;
160
+
161
+ // Export functions
162
+ export function getFullName(first, last) {
163
+ return `${first} ${last}`;
164
+ }
165
+
166
+ // Export default object
167
+ export default {
168
+ items: ["Apple", "Banana", "Cherry"],
169
+ showDetails: true
170
+ };
171
+ </script>
172
+ ```
173
+
174
+ #### 2. Legacy CommonJS (module.exports)
175
+
176
+ ```html
177
+ <script>
178
+ // Legacy CommonJS exports
179
+ module.exports = {
180
+ title: "Hello World",
181
+ items: ["Apple", "Banana", "Cherry"],
182
+ showFooter: true
183
+ };
184
+ </script>
185
+ ```
186
+
187
+ ### Template Directives
188
+
189
+ #### Custom Directives
190
+
191
+ STX supports defining your own custom directives for template processing:
192
+
193
+ ```ts
194
+ import type { CustomDirective } from 'bun-plugin-stx'
195
+ // Configure custom directives
196
+ import stxPlugin from 'bun-plugin-stx'
197
+
198
+ // Create custom directives
199
+ const uppercaseDirective: CustomDirective = {
200
+ name: 'uppercase',
201
+ handler: (content, params) => {
202
+ return params[0] ? params[0].toUpperCase() : content.toUpperCase()
203
+ },
204
+ // No hasEndTag needed for single-parameter directives
205
+ }
206
+
207
+ const wrapDirective: CustomDirective = {
208
+ name: 'wrap',
209
+ handler: (content, params) => {
210
+ const className = params[0] || 'default-wrapper'
211
+ return `<div class="${className}">${content}</div>`
212
+ },
213
+ hasEndTag: true, // This directive requires an end tag (@wrap...@endwrap)
214
+ }
215
+
216
+ // Register custom directives
217
+ await build({
218
+ entrypoints: ['./src/index.ts', './templates/home.stx'],
219
+ outdir: './dist',
220
+ plugins: [stxPlugin],
221
+ stx: {
222
+ customDirectives: [uppercaseDirective, wrapDirective],
223
+ },
224
+ })
225
+ ```
226
+
227
+ Then use them in your templates:
228
+
229
+ ```html
230
+ <!-- Single-parameter directive -->
231
+ <p>@uppercase('hello world')</p>
232
+
233
+ <!-- Block directive with content and optional parameter -->
234
+ @wrap(highlight)
235
+ <p>This content will be wrapped in a div with class "highlight"</p>
236
+ @endwrap
237
+ ```
238
+
239
+ Custom directives have access to:
240
+
241
+ - `content`: The content between start and end tags (for block directives)
242
+ - `params`: Array of parameters passed to the directive
243
+ - `context`: The template data context (all variables)
244
+ - `filePath`: The current template file path
245
+
246
+ #### Variables
247
+
248
+ Display content with double curly braces:
249
+
250
+ ```html
251
+ <h1>{{ title }}</h1>
252
+ <p>{{ user.name }}</p>
253
+ ```
254
+
255
+ #### Conditionals
256
+
257
+ Use `@if`, `@elseif`, and `@else` for conditional rendering:
258
+
259
+ ```html
260
+ @if (user.isAdmin)
261
+ <div class="admin-panel">Admin content</div>
262
+ @elseif (user.isEditor)
263
+ <div class="editor-tools">Editor tools</div>
264
+ @else
265
+ <div class="user-view">Regular user view</div>
266
+ @endif
267
+ ```
268
+
269
+ #### Loops
270
+
271
+ Iterate over arrays with `@foreach`:
272
+
273
+ ```html
274
+ <ul>
275
+ @foreach (items as item)
276
+ <li>{{ item }}</li>
277
+ @endforeach
278
+ </ul>
279
+ ```
280
+
281
+ Use `@for` for numeric loops:
282
+
283
+ ```html
284
+ <ol>
285
+ @for (let i = 1; i <= 5; i++)
286
+ <li>Item {{ i }}</li>
287
+ @endfor
288
+ </ol>
289
+ ```
290
+
291
+ #### Raw HTML
292
+
293
+ Output unescaped HTML content:
294
+
295
+ ```html
296
+ {!! rawHtmlContent !!}
297
+ ```
298
+
299
+ #### Markdown Support
300
+
301
+ STX supports rendering Markdown content directly in your templates using the `@markdown` directive:
302
+
303
+ ```html
304
+ <div class="content">
305
+ @markdown
306
+ # Heading 1
307
+
308
+ This is a paragraph with **bold text** and *italic text*.
309
+
310
+ - List item 1
311
+ - List item 2
312
+ - List item 3
313
+
314
+ ```js
315
+ // Code block
316
+ function hello() {
317
+ console.log('Hello world');
318
+ }
319
+ ```
320
+
321
+ @endmarkdown
322
+ </div>
323
+ ```
324
+
325
+ You can also pass options to the markdown renderer:
326
+
327
+ ```html
328
+ <!-- Enable line breaks (converts single line breaks to <br>) -->
329
+ @markdown(breaks)
330
+ Line 1
331
+ Line 2
332
+ @endmarkdown
333
+
334
+ <!-- Disable GitHub Flavored Markdown -->
335
+ @markdown(no-gfm)
336
+ Content here
337
+ @endmarkdown
338
+ ```
339
+
340
+ ### Internationalization (i18n)
341
+
342
+ STX supports internationalization to help you build multilingual applications. Translation files are stored in YAML format (JSON also supported) and support nested keys and parameter replacements.
343
+
344
+ #### Configuration
345
+
346
+ Configure i18n in your build script:
347
+
348
+ ```js
349
+ import stxPlugin from 'bun-plugin-stx'
350
+
351
+ await build({
352
+ entrypoints: ['./templates/home.stx'],
353
+ outdir: './dist',
354
+ plugins: [stxPlugin],
355
+ stx: {
356
+ i18n: {
357
+ locale: 'en', // Current locale
358
+ defaultLocale: 'en', // Fallback locale
359
+ translationsDir: 'translations', // Directory containing translations
360
+ format: 'yaml', // Format of translation files (yaml, yml, json, or js)
361
+ fallbackToKey: true, // Use key as fallback when translation not found
362
+ cache: true // Cache translations in memory
363
+ }
364
+ }
365
+ })
366
+ ```
367
+
368
+ #### Translation Files
369
+
370
+ Create translation files in your translationsDir:
371
+
372
+ ```yaml
373
+ # translations/en.yaml
374
+ welcome: Welcome to STX
375
+ greeting: Hello, :name!
376
+ nav:
377
+ home: Home
378
+ about: About
379
+ contact: Contact
380
+ ```
381
+
382
+ ```yaml
383
+ # translations/de.yaml
384
+ welcome: Willkommen bei STX
385
+ greeting: Hallo, :name!
386
+ nav:
387
+ home: Startseite
388
+ about: Über uns
389
+ contact: Kontakt
390
+ ```
391
+
392
+ #### Using Translations
393
+
394
+ STX provides multiple ways to use translations in your templates:
395
+
396
+ 1. **@translate Directive**
397
+
398
+ ```html
399
+ <!-- Basic translation -->
400
+ <p>@translate('welcome')</p>
401
+
402
+ <!-- With parameters -->
403
+ <p>@translate('greeting', { "name": "John" })</p>
404
+
405
+ <!-- Nested keys -->
406
+ <p>@translate('nav.home')</p>
407
+
408
+ <!-- With fallback content -->
409
+ <p>@translate('missing.key')Fallback Content@endtranslate</p>
410
+ ```
411
+
412
+ 2. **Filter Syntax**
413
+
414
+ ```html
415
+ <!-- Basic translation as filter -->
416
+ <p>{{ 'welcome' | translate }}</p>
417
+
418
+ <!-- With parameters -->
419
+ <p>{{ 'greeting' | translate({ "name": "Alice" }) }}</p>
420
+
421
+ <!-- Short alias -->
422
+ <p>{{ 'nav.home' | t }}</p>
423
+ ```
424
+
425
+ Parameters in translations use the `:param` syntax, similar to Laravel:
426
+
427
+ ```yaml
428
+ greeting: Hello, :name!
429
+ items: You have :count items in your cart.
430
+ ```
431
+
432
+ Then in your template:
433
+
434
+ ```html
435
+ <p>@translate('greeting', { "name": "John" })</p>
436
+ <p>@translate('items', { "count": 5 })</p>
437
+ ```
438
+
439
+ ### Web Components Integration
440
+
441
+ STX now provides seamless integration with Web Components, allowing you to automatically build and use custom elements from your STX components.
442
+
443
+ #### Configuration
444
+
445
+ Enable web component integration in your build configuration:
446
+
447
+ ```ts
448
+ import { build } from 'bun'
449
+ import stxPlugin from 'bun-plugin-stx'
450
+
451
+ await build({
452
+ entrypoints: ['./templates/home.stx'],
453
+ outdir: './dist',
454
+ plugins: [stxPlugin],
455
+ config: {
456
+ stx: {
457
+ webComponents: {
458
+ enabled: true,
459
+ outputDir: 'dist/web-components',
460
+ components: [
461
+ {
462
+ name: 'MyButton', // Class name for the component
463
+ tag: 'my-button', // HTML tag name (must contain a hyphen)
464
+ file: 'components/button.stx', // Path to the STX component
465
+ attributes: ['type', 'text', 'disabled'] // Observed attributes
466
+ },
467
+ {
468
+ name: 'MyCard',
469
+ tag: 'my-card',
470
+ file: 'components/card.stx',
471
+ shadowDOM: true, // Use Shadow DOM (default: true)
472
+ template: true, // Use template element (default: true)
473
+ styleSource: 'styles/card.css', // Optional external stylesheet
474
+ attributes: ['title', 'footer']
475
+ }
476
+ ]
477
+ }
478
+ }
479
+ }
480
+ })
481
+ ```
482
+
483
+ #### Using Web Components in Templates
484
+
485
+ Include web components in your templates with the `@webcomponent` directive:
486
+
487
+ ```html
488
+ <!DOCTYPE html>
489
+ <html>
490
+ <head>
491
+ <title>Web Component Demo</title>
492
+
493
+ <!-- Include the web components -->
494
+ @webcomponent('my-button')
495
+ @webcomponent('my-card')
496
+ </head>
497
+ <body>
498
+ <h1>Web Components Demo</h1>
499
+
500
+ <!-- Use the custom elements -->
501
+ <my-button type="primary" text="Click Me"></my-button>
502
+
503
+ <my-card title="Card Title" footer="Card Footer">
504
+ This is the card content
505
+ </my-card>
506
+ </body>
507
+ </html>
508
+ ```
509
+
510
+ #### Source STX Components
511
+
512
+ The original STX components can be simple:
513
+
514
+ ```html
515
+ <!-- components/button.stx -->
516
+ <button class="btn {{ type ? 'btn-' + type : '' }}" {{ disabled ? 'disabled' : '' }}>
517
+ {{ text || slot }}
518
+ </button>
519
+
520
+ <!-- components/card.stx -->
521
+ <div class="card">
522
+ <div class="card-header">{{ title }}</div>
523
+ <div class="card-body">
524
+ {{ slot }}
525
+ </div>
526
+ <div class="card-footer">{{ footer }}</div>
527
+ </div>
528
+ ```
529
+
530
+ #### Advanced Options
531
+
532
+ Web components support several configuration options:
533
+
534
+ - `shadowDOM`: Enable/disable Shadow DOM (default: true)
535
+ - `template`: Use template element for better performance (default: true)
536
+ - `extends`: Extend a specific HTML element class
537
+ - `styleSource`: Path to external stylesheet
538
+ - `attributes`: List of attributes to observe for changes
539
+
540
+ ## TypeScript Support
541
+
542
+ STX includes TypeScript declarations for importing .stx files. Make sure your `tsconfig.json` includes the necessary configuration:
543
+
544
+ ```json
545
+ {
546
+ "compilerOptions": {
547
+ // ... your other options
548
+ "types": ["bun"]
549
+ },
550
+ "files": ["src/stx.d.ts"],
551
+ "include": ["**/*.ts", "**/*.d.ts", "*.stx", "./**/*.stx"]
552
+ }
553
+ ```
554
+
555
+ Create a declaration file (`src/stx.d.ts`):
556
+
557
+ ```ts
558
+ // Allow importing .stx files
559
+ declare module '*.stx';
560
+ ```
561
+
562
+ ## Example Server
563
+
564
+ Run a development server with your STX templates:
565
+
566
+ ```ts
567
+ // serve.ts
568
+ import home from './home.stx'
569
+
570
+ const server = Bun.serve({
571
+ routes: {
572
+ '/': home,
573
+ },
574
+ development: true,
575
+
576
+ fetch(req) {
577
+ return new Response('Not Found', { status: 404 })
578
+ },
579
+ })
580
+
581
+ console.log(`Listening on ${server.url}`)
582
+ ```
583
+
584
+ ## Testing This Plugin
585
+
586
+ To test the plugin with the included examples:
587
+
588
+ 1. Build the test file:
589
+
590
+ ```bash
591
+ bun run test-build.ts
592
+ ```
593
+
594
+ 2. Run the test server:
595
+
596
+ ```bash
597
+ bun run serve-test.ts
598
+ ```
599
+
600
+ 3. Open your browser to the displayed URL (typically `http://localhost:3000`).
601
+
602
+ ## How It Works
603
+
604
+ The plugin works by:
605
+
606
+ 1. Extracting script tags from .stx files
607
+ 2. Creating an execution context with variables from the script
608
+ 3. Processing Blade-like directives (@if, @foreach, etc.) into HTML
609
+ 4. Processing variable tags ({{ var }}) with their values
610
+ 5. Returning the processed HTML content
611
+
612
+ ## Testing
613
+
614
+ ```bash
615
+ bun test
616
+ ```
617
+
618
+ ## Changelog
619
+
620
+ Please see our [releases](https://github.com/stacksjs/stx/releases) page for more information on what has changed recently.
621
+
622
+ ## Contributing
623
+
624
+ Please review the [Contributing Guide](https://github.com/stacksjs/contributing) for details.
625
+
626
+ ## Community
627
+
628
+ For help, discussion about best practices, or any other conversation that would benefit from being searchable:
629
+
630
+ [Discussions on GitHub](https://github.com/stacksjs/stacks/discussions)
631
+
632
+ For casual chit-chat with others using this package:
633
+
634
+ [Join the Stacks Discord Server](https://discord.gg/stacksjs)
635
+
636
+ ## Postcardware
637
+
638
+ You will always be free to use any of the Stacks OSS software. We would also love to see which parts of the world Stacks ends up in. _Receiving postcards makes us happy—and we will publish them on our website._
639
+
640
+ Our address: Stacks.js, 12665 Village Ln #2306, Playa Vista, CA 90094, United States 🌎
641
+
642
+ ## Sponsors
643
+
644
+ We would like to extend our thanks to the following sponsors for funding Stacks development. If you are interested in becoming a sponsor, please reach out to us.
645
+
646
+ - [JetBrains](https://www.jetbrains.com/)
647
+ - [The Solana Foundation](https://solana.com/)
648
+
649
+ ## Credits
650
+
651
+ Many thanks to the following core technologies & people who have contributed to this package:
652
+
653
+ - [Laravel](https://laravel.com)
654
+ - [Anthony Fu](https://github.com/antfu)
655
+ - [Chris Breuer](https://github.com/chrisbbreuer)
656
+ - [All Contributors](../../contributors)
657
+
658
+ ## License
659
+
660
+ The MIT License (MIT). Please see [LICENSE](https://github.com/stacksjs/stx/tree/main/LICENSE.md) for more information.
661
+
662
+ Made with 💙
663
+
664
+ <!-- Badges -->
665
+ [npm-version-src]: <https://img.shields.io/npm/v/bun-plugin-stx?style=flat-square>
666
+ [npm-version-href]: <https://npmjs.com/package/bun-plugin-stx>
667
+ [npm-downloads-src]: <https://img.shields.io/npm/dm/bun-plugin-stx?style=flat-square>
668
+ [npm-downloads-href]: <https://npmjs.com/package/bun-plugin-stx>
669
+ [github-actions-src]: <https://img.shields.io/github/actions/workflow/status/stacksjs/stx/ci.yml?style=flat-square&branch=main>
670
+ [github-actions-href]: <https://github.com/stacksjs/stx/actions?query=workflow%3Aci>
671
+
672
+ <!-- [codecov-src]: https://img.shields.io/codecov/c/gh/stacksjs/stx/main?style=flat-square
673
+ [codecov-href]: https://codecov.io/gh/stacksjs/stx -->
674
+
675
+ ## Documentation Generation
676
+
677
+ STX can automatically generate documentation for your components, templates, and directives. This helps developers understand your UI components and how to use them.
678
+
679
+ ### Command Line
680
+
681
+ Generate documentation using the CLI:
682
+
683
+ ```bash
684
+ # Generate markdown documentation (default)
685
+ stx docs
686
+
687
+ # Generate HTML documentation
688
+ stx docs --format html
689
+
690
+ # Generate JSON documentation
691
+ stx docs --format json
692
+
693
+ # Specify output directory
694
+ stx docs --output my-docs
695
+
696
+ # Only generate specific sections
697
+ stx docs --no-components
698
+ stx docs --no-templates
699
+ stx docs --no-directives
700
+
701
+ # Specify custom directories
702
+ stx docs --components-dir src/components --templates-dir src/views
703
+ ```
704
+
705
+ ### Configuration
706
+
707
+ You can configure documentation generation in your `stx.config.ts` file:
708
+
709
+ ```ts
710
+ export default {
711
+ // ...other config options
712
+ docs: {
713
+ enabled: true,
714
+ outputDir: 'docs',
715
+ format: 'markdown', // 'markdown', 'html', or 'json'
716
+ components: true,
717
+ templates: true,
718
+ directives: true,
719
+ extraContent: '## Getting Started\n\nThis is additional content to include in the documentation.',
720
+ },
721
+ };
722
+ ```
723
+
724
+ ### Component Documentation
725
+
726
+ STX can extract component metadata from JSDoc comments in your component files:
727
+
728
+ ```html
729
+ <!--
730
+ Alert component for displaying messages to the user.
731
+ This component supports different types (success, warning, error).
732
+ -->
733
+ <div class="alert alert-{{ type }}">
734
+ <div class="alert-title">{{ title }}</div>
735
+ <div class="alert-body">{{ message }}</div>
736
+ </div>
737
+
738
+ <script>
739
+ /**
740
+ * The type of alert to display
741
+ * @type {string}
742
+ * @default "info"
743
+ */
744
+ const type = module.exports.type || "info";
745
+
746
+ /**
747
+ * The alert title
748
+ * @type {string}
749
+ * @required
750
+ */
751
+ const title = module.exports.title;
752
+
753
+ /**
754
+ * The alert message
755
+ * @type {string}
756
+ */
757
+ const message = module.exports.message || "";
758
+
759
+ // Prepare the component's context
760
+ module.exports = {
761
+ type,
762
+ title,
763
+ message
764
+ };
765
+ </script>
766
+ ```
767
+
768
+ This component will be documented with all its properties, types, default values, and requirements.
769
+
770
+ ### Web Component Documentation
771
+
772
+ STX will automatically document web components defined in your configuration:
773
+
774
+ ```ts
775
+ export default {
776
+ // ... other config
777
+ webComponents: {
778
+ enabled: true,
779
+ outputDir: 'dist/web-components',
780
+ components: [
781
+ {
782
+ name: 'MyButton',
783
+ tag: 'my-button',
784
+ file: 'components/button.stx',
785
+ attributes: ['type', 'text', 'disabled'],
786
+ description: 'A customizable button component'
787
+ }
788
+ ]
789
+ }
790
+ }
791
+ ```
792
+
793
+ The documentation will include:
794
+
795
+ - Component name and description
796
+ - Custom element tag
797
+ - Observed attributes
798
+ - Usage examples
799
+
800
+ This makes it easy for developers to understand how to use your web components in their HTML.