zig-pug 0.2.0 → 0.3.1

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.
Files changed (5) hide show
  1. package/README.md +288 -221
  2. package/binding.gyp +5 -8
  3. package/index.js +11 -33
  4. package/index.mjs +192 -0
  5. package/package.json +32 -24
package/README.md CHANGED
@@ -1,19 +1,23 @@
1
1
  # zig-pug
2
2
 
3
- High-performance Pug template engine powered by Zig and mujs - Native N-API addon with ES5.1 JavaScript support.
3
+ High-performance Pug template engine powered by Zig and mujs.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/zig-pug.svg)](https://www.npmjs.com/package/zig-pug)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![license](https://img.shields.io/npm/l/zig-pug.svg)](https://github.com/carlos-sweb/zig-pug/blob/main/LICENSE)
7
7
 
8
8
  ## Features
9
9
 
10
- - **Blazing Fast**: Written in Zig with native N-API bindings
11
- - **Lightweight**: ~500KB total (includes mujs JavaScript engine)
12
- - **Modern**: Zig 0.15 best practices with StaticStringMap O(1) lookups
13
- - **Secure**: Built-in XSS protection with automatic HTML escaping
14
- - **Simple API**: Easy-to-use JavaScript interface
15
- - **Cross-Platform**: Precompiled binaries for Linux, macOS, and Windows
16
- - **Node.js Compatible**: Works with Node.js 14+ and Bun.js
10
+ - **Pug syntax** - Tags, attributes, classes, IDs
11
+ - **JavaScript expressions** - ES5.1 interpolation powered by mujs
12
+ - **Full UTF-8 support** - Emoji 🎉, accents (á é ñ ü), all Unicode
13
+ - **Documentation comments** - `//!` for file metadata (ignored by parser)
14
+ - **Conditionals** - if/else/unless
15
+ - **Mixins** - Reusable components
16
+ - **Dual package** - CommonJS (`require`) and ES Modules (`import`)
17
+ - ✅ **Bun.js compatible** - 2-5x faster than Node.js
18
+ - ⚡ **Native performance** - Written in Zig, compiled to native code
19
+ - 🔋 **Zero dependencies** - Only Zig and embedded mujs
20
+ - 🌍 **i18n ready** - Spanish, Portuguese, French, German, and more
17
21
 
18
22
  ## Installation
19
23
 
@@ -21,326 +25,389 @@ High-performance Pug template engine powered by Zig and mujs - Native N-API addo
21
25
  npm install zig-pug
22
26
  ```
23
27
 
24
- Precompiled binaries are automatically downloaded for your platform. If no binary is available, it will build from source (requires Zig 0.15+).
28
+ **Requirements:**
29
+ - Node.js >= 14.0.0
30
+ - C/C++ compiler (GCC, Clang, or MSVC)
31
+ - Python (for node-gyp)
32
+
33
+ The addon will compile automatically during installation.
25
34
 
26
35
  ## Quick Start
27
36
 
28
- ```javascript
29
- const { compile } = require('zig-pug');
37
+ ### Simple API
30
38
 
31
- // Simple template
32
- const html = compile('h1 Hello, World!');
33
- console.log(html); // <h1>Hello, World!</h1>
39
+ **CommonJS (Node.js):**
40
+ ```javascript
41
+ const zigpug = require('zig-pug');
34
42
 
35
- // With variables
36
- const html2 = compile('h1 Hello, #{name}!', { name: 'Alice' });
37
- console.log(html2); // <h1>Hello, Alice!</h1>
43
+ const html = zigpug.compile('p Hello #{name}!', { name: 'World' });
44
+ console.log(html);
45
+ // <p>Hello World!</p>
38
46
  ```
39
47
 
40
- ## API Reference
48
+ **ES Modules (Node.js, Bun):**
49
+ ```javascript
50
+ import { compile } from 'zig-pug';
41
51
 
42
- ### compile(template, variables)
52
+ const html = compile('p Hello #{name}!', { name: 'World' });
53
+ console.log(html);
54
+ // <p>Hello World!</p>
55
+ ```
43
56
 
44
- Compile a Pug template string to HTML.
57
+ ### Object-Oriented API
45
58
 
59
+ **CommonJS (Node.js):**
46
60
  ```javascript
47
- const { compile } = require('zig-pug');
61
+ const { PugCompiler } = require('zig-pug');
62
+
63
+ const compiler = new PugCompiler();
64
+ compiler
65
+ .set('title', 'My Page')
66
+ .set('version', 1.5)
67
+ .setBool('isDev', false);
48
68
 
49
- const html = compile('p Hello, #{name}!', { name: 'Bob' });
50
- console.log(html); // <p>Hello, Bob!</p>
69
+ const html = compiler.compile('h1 #{title}');
70
+ console.log(html);
71
+ // <h1>My Page</h1>
51
72
  ```
52
73
 
53
- **Parameters:**
54
- - `template` (string): Pug template string
55
- - `variables` (object, optional): Variables to interpolate
74
+ **ES Modules (Node.js, Bun):**
75
+ ```javascript
76
+ import { PugCompiler } from 'zig-pug';
56
77
 
57
- **Returns:** Compiled HTML string
78
+ const compiler = new PugCompiler();
79
+ compiler
80
+ .set('title', 'My Page')
81
+ .set('version', 1.5)
82
+ .setBool('isDev', false);
58
83
 
59
- ### compileFile(filename, variables)
84
+ const html = compiler.compile('h1 #{title}');
85
+ console.log(html);
86
+ // <h1>My Page</h1>
87
+ ```
60
88
 
61
- Compile a Pug template file to HTML.
89
+ ### Express Integration
62
90
 
63
91
  ```javascript
64
- const { compileFile } = require('zig-pug');
92
+ const express = require('express');
93
+ const zigpug = require('zig-pug');
94
+ const fs = require('fs');
95
+
96
+ const app = express();
97
+
98
+ // Load template once at startup
99
+ const homeTemplate = fs.readFileSync('./views/home.pug', 'utf-8');
65
100
 
66
- const html = compileFile('./views/index.pug', {
67
- title: 'My Page',
68
- user: 'Alice'
101
+ app.get('/', (req, res) => {
102
+ const html = zigpug.compile(homeTemplate, {
103
+ title: 'Home',
104
+ user: req.user
105
+ });
106
+ res.send(html);
69
107
  });
108
+
109
+ app.listen(3000);
70
110
  ```
71
111
 
72
- **Parameters:**
73
- - `filename` (string): Path to Pug template file
74
- - `variables` (object, optional): Variables to interpolate
112
+ ## Bun.js Support
75
113
 
76
- **Returns:** Compiled HTML string
114
+ zig-pug works seamlessly with Bun, the ultra-fast JavaScript runtime:
77
115
 
78
- ### ZigPugCompiler Class
116
+ ```bash
117
+ bun install zig-pug
118
+ bun run app.js
119
+ ```
79
120
 
80
- For multiple compilations, use the `ZigPugCompiler` class to reuse the context:
121
+ **Performance:** Bun is 2-5x faster than Node.js for template compilation.
81
122
 
82
- ```javascript
83
- const { ZigPugCompiler } = require('zig-pug');
123
+ See [examples/bun/](https://github.com/carlos-sweb/zig-pug/tree/main/examples/bun) for complete examples.
84
124
 
85
- const compiler = new ZigPugCompiler();
125
+ ## Pug Syntax
86
126
 
87
- // Set variables
88
- compiler.setString('name', 'Alice');
89
- compiler.setNumber('age', 30);
90
- compiler.setBool('premium', true);
127
+ ### Tags and Attributes
91
128
 
92
- // Or set multiple at once
93
- compiler.setVariables({
94
- name: 'Bob',
95
- age: 25,
96
- premium: false
97
- });
129
+ ```pug
130
+ div.container
131
+ h1#title Hello World
132
+ p.text(data-id="123") Content
133
+ a(href="/" target="_blank") Link
134
+ ```
135
+
136
+ ### JavaScript Interpolation
98
137
 
99
- // Compile templates
100
- const html1 = compiler.compile('p Hello, #{name}!');
101
- const html2 = compiler.compile('p Age: #{age}');
138
+ ```pug
139
+ p Hello #{name}!
140
+ p Age: #{age + 1}
141
+ p Email: #{email.toLowerCase()}
142
+ p Status: #{age >= 18 ? 'Adult' : 'Minor'}
143
+ p Max: #{Math.max(10, 20)}
102
144
  ```
103
145
 
104
- **Methods:**
105
- - `setString(key, value)` - Set a string variable
106
- - `setNumber(key, value)` - Set a number variable
107
- - `setBool(key, value)` - Set a boolean variable
108
- - `set(key, value)` - Auto-detect type and set variable
109
- - `setVariables(obj)` - Set multiple variables from object
110
- - `compile(template)` - Compile template with current variables
111
- - `render(template, variables)` - Set variables and compile in one call
146
+ **Supported JavaScript (ES5.1):**
147
+ - String methods: `toLowerCase()`, `toUpperCase()`, `split()`, etc.
148
+ - Math: `Math.max()`, `Math.min()`, `Math.random()`, etc.
149
+ - Operators: `+`, `-`, `*`, `/`, `%`, `&&`, `||`, `?:`
150
+ - Object/Array access: `obj.prop`, `arr[0]`, `arr.length`
112
151
 
113
- ### version()
152
+ ### Conditionals
114
153
 
115
- Get the zig-pug version.
154
+ ```pug
155
+ if isLoggedIn
156
+ p Welcome back!
157
+ else
158
+ p Please log in
116
159
 
117
- ```javascript
118
- const { version } = require('zig-pug');
119
- console.log(version()); // 0.2.0
160
+ unless isAdmin
161
+ p Access denied
120
162
  ```
121
163
 
122
- ## Pug Syntax Support
123
-
124
- ### Tags
164
+ ### Mixins
125
165
 
126
166
  ```pug
127
- div
128
- p Hello, World!
129
- span.class-name#id-name Text content
130
- ```
167
+ mixin button(text)
168
+ button.btn= text
131
169
 
132
- ```html
133
- <div>
134
- <p>Hello, World!</p>
135
- <span class="class-name" id="id-name">Text content</span>
136
- </div>
170
+ +button('Click me')
171
+ +button('Submit')
137
172
  ```
138
173
 
139
- ### Attributes
174
+ ### UTF-8 & Unicode Support
175
+
176
+ Full support for international characters, emoji, and symbols:
140
177
 
141
178
  ```pug
142
- a(href="https://example.com" target="_blank") Link
143
- input(type="text" name="username" required)
179
+ //! File: index.pug
180
+ //! Author: Carlos
181
+ doctype html
182
+ html(lang="es")
183
+ head
184
+ title #{titulo}
185
+ body
186
+ h1 ¡Bienvenido! 🎉
187
+
188
+ section.español
189
+ p.información Información sobre José y María
190
+ p#descripción Este párrafo tiene ID con acento
191
+
192
+ section.português
193
+ h2 Programação em português
194
+ p Características: ã, õ, ç
195
+
196
+ section.français
197
+ h2 Génération française
198
+ p Avec é, è, ê, ç
199
+
200
+ footer
201
+ p © 2025 - Creado con zig-pug 🚀
144
202
  ```
145
203
 
146
- ```html
147
- <a href="https://example.com" target="_blank">Link</a>
148
- <input type="text" name="username" required />
149
- ```
204
+ **Supported everywhere:**
205
+ - Text content: `p José, María, Ángel`
206
+ - Class names: `.información .português`
207
+ - ✅ ID attributes: `#descripción #größe`
208
+ - ✅ Comments: `// útil para depuración`
209
+ - ✅ Emoji: `h1 Hello 🎉 🚀 ✨`
210
+ - ✅ Symbols: `p © ™ € £ ¥`
211
+
212
+ ### Documentation Comments
150
213
 
151
- ### Interpolation
214
+ Use `//!` for file metadata that won't appear in output:
152
215
 
153
216
  ```pug
154
- p Hello, #{name}!
155
- p Age: #{age}
156
- p Premium: #{premium}
217
+ //! Template: homepage.pug
218
+ //! Author: John Doe
219
+ //! Version: 1.0
220
+ //! Description: Main landing page
221
+ doctype html
222
+ html
223
+ body
224
+ // Regular comment (appears in --pretty mode)
225
+ //- Code comment (never appears)
157
226
  ```
158
227
 
159
- With variables: `{ name: 'Alice', age: 30, premium: true }`
228
+ | Syntax | Name | In HTML? | Use Case |
229
+ |--------|------|----------|----------|
230
+ | `//!` | Documentation | ❌ Never | File metadata, notes |
231
+ | `//` | Buffered | ✅ Dev mode | Development debugging |
232
+ | `//-` | Unbuffered | ❌ Never | Code comments |
160
233
 
161
- ```html
162
- <p>Hello, Alice!</p>
163
- <p>Age: 30</p>
164
- <p>Premium: true</p>
165
- ```
234
+ ## API Reference
235
+
236
+ ### `compile(template, data)`
166
237
 
167
- ### HTML Escaping
238
+ Compile a template with data.
239
+
240
+ **Parameters:**
241
+ - `template` (string) - Pug template source
242
+ - `data` (object) - Variables to interpolate
168
243
 
169
- Automatic XSS protection:
244
+ **Returns:** (string) Compiled HTML
170
245
 
171
246
  ```javascript
172
- const html = compile('p #{userInput}', {
173
- userInput: '<script>alert("XSS")</script>'
174
- });
175
- // <p>&lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;</p>
247
+ const html = zigpug.compile(
248
+ 'p Hello #{name}!',
249
+ { name: 'Alice' }
250
+ );
176
251
  ```
177
252
 
178
- ### Void Elements
253
+ ### `PugCompiler`
179
254
 
180
- Self-closing tags are handled automatically:
255
+ Reusable compiler with state.
181
256
 
182
- ```pug
183
- br
184
- hr
185
- img(src="logo.png")
186
- input(type="text")
187
- ```
257
+ ```javascript
258
+ const { PugCompiler } = require('zig-pug');
259
+
260
+ const compiler = new PugCompiler();
261
+ compiler.set('key', 'value'); // String/Number
262
+ compiler.setBool('flag', true); // Boolean
188
263
 
189
- ```html
190
- <br />
191
- <hr />
192
- <img src="logo.png" />
193
- <input type="text" />
264
+ const html = compiler.compile(template);
194
265
  ```
195
266
 
196
- ## Usage Examples
267
+ **Methods:**
268
+ - `set(key, value)` - Set string or number variable
269
+ - `setBool(key, value)` - Set boolean variable
270
+ - `compile(template)` - Compile template with current variables
197
271
 
198
- ### Express Integration
272
+ ### `version()`
273
+
274
+ Get zig-pug version.
199
275
 
200
276
  ```javascript
201
- const express = require('express');
202
- const { compileFile } = require('zig-pug');
203
- const app = express();
277
+ console.log(zigpug.version()); // "0.2.0"
278
+ ```
204
279
 
205
- app.get('/', (req, res) => {
206
- const html = compileFile('./views/index.pug', {
207
- title: 'Home Page',
208
- user: req.user
209
- });
210
- res.send(html);
211
- });
280
+ ## Platform Support
212
281
 
213
- app.listen(3000);
214
- ```
282
+ ### Supported Platforms
215
283
 
216
- ### Koa Integration
284
+ - **Linux** (x64, ARM64)
285
+ - ✅ **macOS** (x64, Apple Silicon)
286
+ - ✅ **Windows** (x64)
287
+ - ✅ **Bun.js** (all platforms)
217
288
 
218
- ```javascript
219
- const Koa = require('koa');
220
- const { compileFile } = require('zig-pug');
221
- const app = new Koa();
222
-
223
- app.use(async ctx => {
224
- const html = compileFile('./views/index.pug', {
225
- title: 'Home Page',
226
- path: ctx.path
227
- });
228
- ctx.body = html;
229
- });
289
+ ### Termux/Android
230
290
 
231
- app.listen(3000);
232
- ```
291
+ The addon compiles on Termux but cannot be loaded due to Android namespace restrictions. Use the standalone CLI binary instead:
233
292
 
234
- ### Bun.js Integration
293
+ ```bash
294
+ # Install Zig
295
+ pkg install zig
235
296
 
236
- ```javascript
237
- import { compile } from 'zig-pug';
297
+ # Clone and build
298
+ git clone https://github.com/yourusername/zig-pug
299
+ cd zig-pug
300
+ zig build
238
301
 
239
- Bun.serve({
240
- port: 3000,
241
- fetch(req) {
242
- const html = compile('h1 Hello from Bun!');
243
- return new Response(html, {
244
- headers: { 'Content-Type': 'text/html' }
245
- });
246
- }
247
- });
302
+ # Use CLI
303
+ ./zig-out/bin/zig-pug template.pug
248
304
  ```
249
305
 
306
+ See [docs/TERMUX.md](https://github.com/yourusername/zig-pug/blob/main/docs/TERMUX.md) for details.
307
+
250
308
  ## Performance
251
309
 
252
- zig-pug is designed for performance:
310
+ ### Benchmark
253
311
 
254
- - **O(1) lookups**: StaticStringMap for void element checks
255
- - **Optimized I/O**: Writer pattern reduces allocations
256
- - **Native code**: Zig compiles to machine code
257
- - **Lightweight**: No heavy dependencies
258
- - **Fast startup**: mujs has minimal overhead
312
+ ```javascript
313
+ const iterations = 10000;
314
+ const start = Date.now();
259
315
 
260
- ## Security
316
+ for (let i = 0; i < iterations; i++) {
317
+ zigpug.compile(template, data);
318
+ }
261
319
 
262
- - **Automatic HTML escaping**: All interpolated values are escaped by default
263
- - **XSS prevention**: Built-in protection against cross-site scripting
264
- - **Safe parsing**: Zig's memory safety prevents buffer overflows
265
- - **No eval()**: Templates are compiled, not evaluated
320
+ const elapsed = Date.now() - start;
321
+ console.log(`${iterations} in ${elapsed}ms`);
322
+ // ~100-250k ops/sec depending on runtime
323
+ ```
266
324
 
267
- ## Building from Source
325
+ ### Tips
268
326
 
269
- If precompiled binaries are not available for your platform:
327
+ 1. **Reuse PugCompiler** - Faster than creating new context each time
328
+ 2. **Pre-load templates** - Read files once at startup
329
+ 3. **Use Bun.js** - 2-5x faster than Node.js
270
330
 
271
- ### Prerequisites
331
+ ## Examples
272
332
 
273
- - Node.js 14+
274
- - Zig 0.15+
275
- - Python 3
276
- - C compiler (gcc/clang)
333
+ See the [examples](https://github.com/yourusername/zig-pug/tree/main/examples) directory:
277
334
 
278
- ### Build Steps
335
+ - **Node.js**: `examples/nodejs/`
336
+ - **Bun.js**: `examples/bun/`
337
+ - **Express**: `examples/nodejs/05-express-integration.js`
279
338
 
280
- From the repository root:
339
+ ## Documentation
281
340
 
282
- ```bash
283
- # Build the addon (builds library + addon + copies library to build dir)
284
- zig build node
341
+ - **[Getting Started](https://github.com/yourusername/zig-pug/blob/main/docs/GETTING-STARTED.md)**
342
+ - **[Node.js Integration](https://github.com/yourusername/zig-pug/blob/main/docs/NODEJS-INTEGRATION.md)**
343
+ - **[Pug Syntax Reference](https://github.com/yourusername/zig-pug/blob/main/docs/PUG-SYNTAX.md)**
344
+ - **[API Reference](https://github.com/yourusername/zig-pug/blob/main/docs/API-REFERENCE.md)**
285
345
 
286
- # Or from nodejs directory
287
- cd nodejs && npm run build
288
- ```
346
+ ## Troubleshooting
347
+
348
+ ### Installation fails
349
+
350
+ **Error:** `node-gyp rebuild` fails
289
351
 
290
- ### Running Examples and Tests
352
+ **Solution:** Install build tools:
291
353
 
292
354
  ```bash
293
- # From nodejs directory
294
- npm test # Run test suite
295
- npm run example # Run example
355
+ # Ubuntu/Debian
356
+ sudo apt-get install build-essential python3
296
357
 
297
- # Or directly with node (after building)
298
- node test/test.js
299
- node example.js
358
+ # macOS
359
+ xcode-select --install
360
+
361
+ # Windows
362
+ npm install --global windows-build-tools
300
363
  ```
301
364
 
302
- **Note:** The build process automatically copies `libzigpug.so` to the `build/Release/` directory, so you don't need to set `LD_LIBRARY_PATH` manually.
365
+ ### Module not found
303
366
 
304
- See [BUILD_GUIDE.md](BUILD_GUIDE.md) for detailed build instructions.
367
+ **Error:** `Cannot find module 'zig-pug'`
305
368
 
306
- ## Architecture
369
+ **Solution:** Rebuild the addon:
307
370
 
371
+ ```bash
372
+ cd node_modules/zig-pug
373
+ npm run build
308
374
  ```
309
- ┌─────────────────────────────────────────────┐
310
- │ Node.js Application │
311
- │ (your code) │
312
- └────────────┬────────────────────────────────┘
313
- require('zig-pug')
314
-
315
- ┌─────────────────────────────────────────────┐
316
- │ N-API Addon (binding.c) │
317
- │ - JavaScript API wrapper │
318
- └────────────┬────────────────────────────────┘
319
- │ FFI calls
320
-
321
- ┌─────────────────────────────────────────────┐
322
- │ libzigpug.so (Zig + mujs) │
323
- │ - Tokenizer → Parser → Compiler → HTML │
324
- └─────────────────────────────────────────────┘
325
- ```
375
+
376
+ ### Compilation errors
377
+
378
+ If you encounter compilation errors, please [open an issue](https://github.com/yourusername/zig-pug/issues) with:
379
+ - Your OS and version
380
+ - Node.js version (`node --version`)
381
+ - Complete error output
326
382
 
327
383
  ## Contributing
328
384
 
329
- Contributions are welcome! Please see the main repository for contributing guidelines.
385
+ Contributions are welcome! Please:
386
+
387
+ 1. Fork the repository
388
+ 2. Create a feature branch
389
+ 3. Make your changes
390
+ 4. Run tests: `npm test`
391
+ 5. Submit a pull request
330
392
 
331
393
  ## License
332
394
 
333
- MIT License - see [LICENSE](LICENSE) for details.
395
+ MIT License - see [LICENSE](https://github.com/yourusername/zig-pug/blob/main/LICENSE) for details.
396
+
397
+ ## Credits
398
+
399
+ - **[Pug](https://pugjs.org/)** - Original inspiration
400
+ - **[Zig](https://ziglang.org/)** - Programming language
401
+ - **[mujs](https://mujs.com/)** - Embedded JavaScript engine
402
+ - **[Artifex Software](https://artifex.com/)** - Creators of mujs
334
403
 
335
404
  ## Links
336
405
 
337
- - [GitHub Repository](https://github.com/carlos-sweb/zig-pug)
338
- - [npm Package](https://www.npmjs.com/package/zig-pug)
339
- - [Issue Tracker](https://github.com/carlos-sweb/zig-pug/issues)
340
- - [Build Guide](BUILD_GUIDE.md)
406
+ - **GitHub**: https://github.com/yourusername/zig-pug
407
+ - **npm**: https://www.npmjs.com/package/zig-pug
408
+ - **Issues**: https://github.com/yourusername/zig-pug/issues
409
+ - **Documentation**: https://github.com/yourusername/zig-pug#readme
341
410
 
342
- ## Credits
411
+ ---
343
412
 
344
- - Built by [carlos-sweb](https://github.com/carlos-sweb)
345
- - Powered by [Zig](https://ziglang.org/) and [mujs](https://mujs.com/)
346
- - Inspired by the original [Pug](https://pugjs.org/) template engine
413
+ Made with ❤️ using Zig 0.15.2 and mujs
package/binding.gyp CHANGED
@@ -3,25 +3,22 @@
3
3
  {
4
4
  "target_name": "zigpug",
5
5
  "sources": [
6
- "binding.c"
6
+ "binding.c",
7
+ "vendor/mujs/one.c"
7
8
  ],
8
9
  "include_dirs": [
9
10
  "include",
10
- "../vendor/mujs"
11
+ "vendor/mujs"
11
12
  ],
12
13
  "libraries": [
13
- "-L<(module_root_dir)",
14
- "-lzigpug",
15
14
  "-lm"
16
15
  ],
17
16
  "cflags": [
18
- "-std=c99"
17
+ "-std=c99",
18
+ "-DHAVE_STRLCPY=0"
19
19
  ],
20
20
  "defines": [
21
21
  "NAPI_VERSION=8"
22
- ],
23
- "ldflags": [
24
- "-Wl,-rpath,'$$ORIGIN'"
25
22
  ]
26
23
  }
27
24
  ]
package/index.js CHANGED
@@ -3,32 +3,12 @@
3
3
  * Powered by Zig and mujs
4
4
  */
5
5
 
6
- const binary = require('@mapbox/node-pre-gyp');
7
- const path = require('path');
8
- const fs = require('fs');
9
-
10
- // Try to find precompiled binary first, fallback to development build
11
- let binding;
12
- try {
13
- const binding_path = binary.find(path.resolve(path.join(__dirname, './package.json')));
14
- binding = require(binding_path);
15
- } catch (err) {
16
- // Fallback to development build location
17
- const dev_path = path.join(__dirname, 'build', 'Release', 'zigpug.node');
18
- if (fs.existsSync(dev_path)) {
19
- binding = require(dev_path);
20
- } else {
21
- throw new Error(
22
- 'zig-pug native addon not found. ' +
23
- 'Please build it with: cd .. && zig build node'
24
- );
25
- }
26
- }
6
+ const binding = require('./build/Release/zigpug.node');
27
7
 
28
8
  /**
29
- * ZigPugCompiler class - High-level API for compiling Pug templates
9
+ * PugCompiler class - High-level API for compiling Pug templates
30
10
  */
31
- class ZigPugCompiler {
11
+ class PugCompiler {
32
12
  constructor() {
33
13
  this.context = binding.createContext();
34
14
  if (!this.context) {
@@ -40,7 +20,7 @@ class ZigPugCompiler {
40
20
  * Set a string variable in the template context
41
21
  * @param {string} key - Variable name
42
22
  * @param {string} value - String value
43
- * @returns {ZigPugCompiler} - Returns this for chaining
23
+ * @returns {PugCompiler} - Returns this for chaining
44
24
  */
45
25
  setString(key, value) {
46
26
  if (typeof key !== 'string') {
@@ -61,7 +41,7 @@ class ZigPugCompiler {
61
41
  * Set a number variable in the template context
62
42
  * @param {string} key - Variable name
63
43
  * @param {number} value - Number value
64
- * @returns {ZigPugCompiler} - Returns this for chaining
44
+ * @returns {PugCompiler} - Returns this for chaining
65
45
  */
66
46
  setNumber(key, value) {
67
47
  if (typeof key !== 'string') {
@@ -82,7 +62,7 @@ class ZigPugCompiler {
82
62
  * Set a boolean variable in the template context
83
63
  * @param {string} key - Variable name
84
64
  * @param {boolean} value - Boolean value
85
- * @returns {ZigPugCompiler} - Returns this for chaining
65
+ * @returns {PugCompiler} - Returns this for chaining
86
66
  */
87
67
  setBool(key, value) {
88
68
  if (typeof key !== 'string') {
@@ -103,7 +83,7 @@ class ZigPugCompiler {
103
83
  * Set a variable (automatically detects type)
104
84
  * @param {string} key - Variable name
105
85
  * @param {string|number|boolean} value - Value of any supported type
106
- * @returns {ZigPugCompiler} - Returns this for chaining
86
+ * @returns {PugCompiler} - Returns this for chaining
107
87
  */
108
88
  set(key, value) {
109
89
  if (typeof value === 'string') {
@@ -120,7 +100,7 @@ class ZigPugCompiler {
120
100
  /**
121
101
  * Set multiple variables from an object
122
102
  * @param {Object} variables - Object with key-value pairs
123
- * @returns {ZigPugCompiler} - Returns this for chaining
103
+ * @returns {PugCompiler} - Returns this for chaining
124
104
  */
125
105
  setVariables(variables) {
126
106
  if (typeof variables !== 'object' || variables === null) {
@@ -171,7 +151,7 @@ class ZigPugCompiler {
171
151
  * @returns {string} - Compiled HTML
172
152
  */
173
153
  function compile(template, variables = {}) {
174
- const compiler = new ZigPugCompiler();
154
+ const compiler = new PugCompiler();
175
155
  return compiler.render(template, variables);
176
156
  }
177
157
 
@@ -196,10 +176,8 @@ function version() {
196
176
  }
197
177
 
198
178
  module.exports = {
199
- ZigPugCompiler,
179
+ PugCompiler,
200
180
  compile,
201
181
  compileFile,
202
- version,
203
- // Backward compatibility alias
204
- PugCompiler: ZigPugCompiler
182
+ version
205
183
  };
package/index.mjs ADDED
@@ -0,0 +1,192 @@
1
+ /**
2
+ * zig-pug - Pug template engine for Node.js (ES Module version)
3
+ * Powered by Zig and mujs
4
+ */
5
+
6
+ import { createRequire } from 'module';
7
+ import { fileURLToPath } from 'url';
8
+ import { dirname } from 'path';
9
+ import { readFileSync } from 'fs';
10
+
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+ const require = createRequire(import.meta.url);
14
+
15
+ const binding = require('./build/Release/zigpug.node');
16
+
17
+ /**
18
+ * PugCompiler class - High-level API for compiling Pug templates
19
+ */
20
+ export class PugCompiler {
21
+ constructor() {
22
+ this.context = binding.createContext();
23
+ if (!this.context) {
24
+ throw new Error('Failed to create zig-pug context');
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Set a string variable in the template context
30
+ * @param {string} key - Variable name
31
+ * @param {string} value - String value
32
+ * @returns {PugCompiler} - Returns this for chaining
33
+ */
34
+ setString(key, value) {
35
+ if (typeof key !== 'string') {
36
+ throw new TypeError('Key must be a string');
37
+ }
38
+ if (typeof value !== 'string') {
39
+ throw new TypeError('Value must be a string');
40
+ }
41
+
42
+ const success = binding.setString(this.context, key, value);
43
+ if (!success) {
44
+ throw new Error(`Failed to set string variable: ${key}`);
45
+ }
46
+ return this;
47
+ }
48
+
49
+ /**
50
+ * Set a number variable in the template context
51
+ * @param {string} key - Variable name
52
+ * @param {number} value - Number value
53
+ * @returns {PugCompiler} - Returns this for chaining
54
+ */
55
+ setNumber(key, value) {
56
+ if (typeof key !== 'string') {
57
+ throw new TypeError('Key must be a string');
58
+ }
59
+ if (typeof value !== 'number') {
60
+ throw new TypeError('Value must be a number');
61
+ }
62
+
63
+ const success = binding.setNumber(this.context, key, Math.floor(value));
64
+ if (!success) {
65
+ throw new Error(`Failed to set number variable: ${key}`);
66
+ }
67
+ return this;
68
+ }
69
+
70
+ /**
71
+ * Set a boolean variable in the template context
72
+ * @param {string} key - Variable name
73
+ * @param {boolean} value - Boolean value
74
+ * @returns {PugCompiler} - Returns this for chaining
75
+ */
76
+ setBool(key, value) {
77
+ if (typeof key !== 'string') {
78
+ throw new TypeError('Key must be a string');
79
+ }
80
+ if (typeof value !== 'boolean') {
81
+ throw new TypeError('Value must be a boolean');
82
+ }
83
+
84
+ const success = binding.setBool(this.context, key, value);
85
+ if (!success) {
86
+ throw new Error(`Failed to set boolean variable: ${key}`);
87
+ }
88
+ return this;
89
+ }
90
+
91
+ /**
92
+ * Set a variable (automatically detects type)
93
+ * @param {string} key - Variable name
94
+ * @param {string|number|boolean} value - Value of any supported type
95
+ * @returns {PugCompiler} - Returns this for chaining
96
+ */
97
+ set(key, value) {
98
+ if (typeof value === 'string') {
99
+ return this.setString(key, value);
100
+ } else if (typeof value === 'number') {
101
+ return this.setNumber(key, value);
102
+ } else if (typeof value === 'boolean') {
103
+ return this.setBool(key, value);
104
+ } else {
105
+ throw new TypeError(`Unsupported value type for key "${key}": ${typeof value}`);
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Set multiple variables from an object
111
+ * @param {Object} variables - Object with key-value pairs
112
+ * @returns {PugCompiler} - Returns this for chaining
113
+ */
114
+ setVariables(variables) {
115
+ if (typeof variables !== 'object' || variables === null) {
116
+ throw new TypeError('Variables must be an object');
117
+ }
118
+
119
+ for (const [key, value] of Object.entries(variables)) {
120
+ this.set(key, value);
121
+ }
122
+
123
+ return this;
124
+ }
125
+
126
+ /**
127
+ * Compile a Pug template to HTML
128
+ * @param {string} template - Pug template string
129
+ * @returns {string} - Compiled HTML
130
+ */
131
+ compile(template) {
132
+ if (typeof template !== 'string') {
133
+ throw new TypeError('Template must be a string');
134
+ }
135
+
136
+ const html = binding.compile(this.context, template);
137
+ if (!html) {
138
+ throw new Error('Failed to compile template');
139
+ }
140
+
141
+ return html;
142
+ }
143
+
144
+ /**
145
+ * Compile a template with variables in one call
146
+ * @param {string} template - Pug template string
147
+ * @param {Object} variables - Variables to set before compiling
148
+ * @returns {string} - Compiled HTML
149
+ */
150
+ render(template, variables = {}) {
151
+ this.setVariables(variables);
152
+ return this.compile(template);
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Convenience function to compile a template with variables
158
+ * @param {string} template - Pug template string
159
+ * @param {Object} variables - Variables for the template
160
+ * @returns {string} - Compiled HTML
161
+ */
162
+ export function compile(template, variables = {}) {
163
+ const compiler = new PugCompiler();
164
+ return compiler.render(template, variables);
165
+ }
166
+
167
+ /**
168
+ * Convenience function to compile a template from a file
169
+ * @param {string} filename - Path to the Pug template file
170
+ * @param {Object} variables - Variables for the template
171
+ * @returns {string} - Compiled HTML
172
+ */
173
+ export function compileFile(filename, variables = {}) {
174
+ const template = readFileSync(filename, 'utf8');
175
+ return compile(template, variables);
176
+ }
177
+
178
+ /**
179
+ * Get the zig-pug version
180
+ * @returns {string} - Version string
181
+ */
182
+ export function version() {
183
+ return binding.version();
184
+ }
185
+
186
+ // Default export for compatibility
187
+ export default {
188
+ PugCompiler,
189
+ compile,
190
+ compileFile,
191
+ version
192
+ };
package/package.json CHANGED
@@ -1,20 +1,21 @@
1
1
  {
2
2
  "name": "zig-pug",
3
- "version": "0.2.0",
4
- "description": "High-performance Pug template engine powered by Zig and mujs - Native N-API addon with ES5.1 JavaScript support",
3
+ "version": "0.3.1",
4
+ "description": "High-performance Pug template engine powered by Zig and mujs. Native N-API addon with ES5.1 JavaScript support, full UTF-8 (emoji, accents), documentation comments (//!), and fast compilation. Compatible with Node.js and Bun.",
5
+ "type": "commonjs",
5
6
  "main": "index.js",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./index.mjs",
10
+ "require": "./index.js"
11
+ }
12
+ },
6
13
  "scripts": {
7
- "install": "node-pre-gyp install --fallback-to-build || (cd .. && zig build node)",
8
- "build": "cd .. && zig build node",
9
- "build:from-source": "cd .. && zig build node",
10
- "rebuild": "node-gyp rebuild && npm run postbuild",
11
- "postbuild": "cp ../zig-out/nodejs/libzigpug.* build/Release/ 2>/dev/null || true",
12
- "clean": "node-gyp clean && rm -rf ../zig-out/nodejs lib/binding",
13
- "test": "LD_LIBRARY_PATH=../zig-out/nodejs:$LD_LIBRARY_PATH node test/test.js",
14
- "example": "LD_LIBRARY_PATH=../zig-out/nodejs:$LD_LIBRARY_PATH node example.js",
15
- "package": "node-pre-gyp package",
16
- "upload": "node-pre-gyp publish",
17
- "upload:github": "node scripts/upload-binary.js",
14
+ "install": "node-gyp rebuild",
15
+ "build": "node-gyp configure build",
16
+ "rebuild": "node-gyp rebuild",
17
+ "clean": "node-gyp clean",
18
+ "test": "node test/test.js",
18
19
  "prepublishOnly": "npm run build"
19
20
  },
20
21
  "keywords": [
@@ -40,11 +41,22 @@
40
41
  "view-engine",
41
42
  "express",
42
43
  "jade",
43
- "haml"
44
+ "haml",
45
+ "utf-8",
46
+ "utf8",
47
+ "unicode",
48
+ "emoji",
49
+ "i18n",
50
+ "internationalization",
51
+ "multilingual",
52
+ "spanish",
53
+ "portuguese",
54
+ "french",
55
+ "german"
44
56
  ],
45
57
  "author": {
46
- "name": "carlos-sweb",
47
- "url": "https://github.com/carlos-sweb"
58
+ "name": "zig-pug contributors",
59
+ "url": "https://github.com/carlos-sweb/zig-pug/graphs/contributors"
48
60
  },
49
61
  "license": "MIT",
50
62
  "repository": {
@@ -59,23 +71,19 @@
59
71
  "engines": {
60
72
  "node": ">=14.0.0"
61
73
  },
62
- "dependencies": {
63
- "@mapbox/node-pre-gyp": "^1.0.11"
64
- },
74
+ "dependencies": {},
65
75
  "devDependencies": {
66
- "node-gyp": "^10.0.0",
67
- "aws-sdk": "^2.1691.0"
76
+ "node-gyp": "^10.0.0"
68
77
  },
69
78
  "gypfile": true,
70
79
  "binary": {
71
80
  "module_name": "zigpug",
72
- "module_path": "./lib/binding/{configuration}/{node_abi}-{platform}-{arch}",
73
- "remote_path": "./{version}",
74
- "package_name": "{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz",
81
+ "module_path": "./build/Release/",
75
82
  "host": "https://github.com/carlos-sweb/zig-pug/releases/download/"
76
83
  },
77
84
  "files": [
78
85
  "index.js",
86
+ "index.mjs",
79
87
  "binding.c",
80
88
  "binding.gyp",
81
89
  "common.gypi",