puglite 1.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 +115 -0
- package/angular-webpack/index.js +27 -0
- package/angular-webpack/loader.js +37 -0
- package/builders/browser/index.js +49 -0
- package/builders/browser/schema.json +138 -0
- package/builders/dev-server/index.js +48 -0
- package/builders/dev-server/schema.json +98 -0
- package/builders/karma/README.md +82 -0
- package/builders/karma/index.js +40 -0
- package/builders/karma/schema.json +260 -0
- package/builders/vitest/README.md +218 -0
- package/builders/vitest/index.js +98 -0
- package/builders/vitest/schema.json +8 -0
- package/builders.json +25 -0
- package/lib/attrs.js +150 -0
- package/lib/build.js +27 -0
- package/lib/code-gen.js +769 -0
- package/lib/error.js +56 -0
- package/lib/index.js +416 -0
- package/lib/lexer.d.ts +366 -0
- package/lib/lexer.js +1713 -0
- package/lib/parser-lib/inline-tags.js +23 -0
- package/lib/parser.js +1299 -0
- package/lib/prepublish.js +70 -0
- package/lib/runtime-build.js +27 -0
- package/lib/runtime-lib/dependencies.js +34 -0
- package/lib/runtime-lib/internals.js +8 -0
- package/lib/runtime-lib/sources.js +13 -0
- package/lib/runtime-wrap.js +10 -0
- package/lib/runtime.js +287 -0
- package/lib/strip-comments.js +77 -0
- package/lib/wrap.js +10 -0
- package/package.json +72 -0
package/README.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Puglite
|
|
2
|
+
|
|
3
|
+
A lightweight, streamlined version of the Pug template engine.
|
|
4
|
+
|
|
5
|
+
## What is Puglite?
|
|
6
|
+
|
|
7
|
+
Puglite is a refactored version of [Pug](https://github.com/pugjs/pug) with simplified features:
|
|
8
|
+
- ✅ Clean whitespace-sensitive syntax
|
|
9
|
+
- ✅ Tags, classes, IDs, attributes
|
|
10
|
+
- ✅ Compile-time transformation
|
|
11
|
+
- ❌ No logic flow (if/else, loops)
|
|
12
|
+
- ❌ No mixins
|
|
13
|
+
- ❌ No interpolation
|
|
14
|
+
|
|
15
|
+
## Credits & Thanks
|
|
16
|
+
|
|
17
|
+
**Puglite is built upon [Pug](https://pugjs.org).** All core parsing and compilation code comes from the excellent Pug project. We simply removed features to create a more focused template engine.
|
|
18
|
+
|
|
19
|
+
Huge thanks to:
|
|
20
|
+
- **TJ Holowaychuk** - Pug creator
|
|
21
|
+
- **Forbes Lindesay** - Pug maintainer
|
|
22
|
+
- **The Pug.js team and all contributors**
|
|
23
|
+
|
|
24
|
+
Without their amazing work, Puglite wouldn't exist. ❤️
|
|
25
|
+
|
|
26
|
+
Special thanks to **Adam Miller** for sponsoring the Claude Code usage that helped build Puglite.
|
|
27
|
+
|
|
28
|
+
## Standalone Usage
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
const puglite = require('puglite');
|
|
32
|
+
|
|
33
|
+
const html = puglite.render('.container\n h1 Hello\n p World');
|
|
34
|
+
// <div class="container"><h1>Hello</h1><p>World</p></div>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick Start with Angular 18+
|
|
38
|
+
|
|
39
|
+
### 1. Install
|
|
40
|
+
```bash
|
|
41
|
+
npm install -D puglite @angular-builders/custom-webpack
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 2. Update `angular.json`
|
|
45
|
+
|
|
46
|
+
Use `puglite:browser` and `puglite:dev-server` builders:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"architect": {
|
|
51
|
+
"build": {
|
|
52
|
+
"builder": "puglite:browser",
|
|
53
|
+
"options": {
|
|
54
|
+
"outputPath": "dist/my-app",
|
|
55
|
+
"index": "src/index.html",
|
|
56
|
+
"main": "src/main.ts",
|
|
57
|
+
"tsConfig": "tsconfig.app.json"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"serve": {
|
|
61
|
+
"builder": "puglite:dev-server",
|
|
62
|
+
"configurations": {
|
|
63
|
+
"development": {
|
|
64
|
+
"buildTarget": "my-app:build:development"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Important:** Puglite requires the **old Angular schema format** with `outputPath`, `index`, and `main`. The new Angular 17+ schema using `browser` instead of `main` is not supported because puglite uses webpack-based builds.
|
|
73
|
+
|
|
74
|
+
### 3. Use `.pug` Templates
|
|
75
|
+
```typescript
|
|
76
|
+
@Component({
|
|
77
|
+
selector: 'app-root',
|
|
78
|
+
templateUrl: './app.component.pug'
|
|
79
|
+
})
|
|
80
|
+
export class AppComponent {
|
|
81
|
+
title = 'My App';
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**app.component.pug:**
|
|
86
|
+
```pug
|
|
87
|
+
.container
|
|
88
|
+
h1 {{ title }}
|
|
89
|
+
p Welcome to Puglite!
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Supported Syntax
|
|
93
|
+
|
|
94
|
+
See EXAMPLES.md
|
|
95
|
+
|
|
96
|
+
## What's Different from Pug?
|
|
97
|
+
|
|
98
|
+
Puglite **removes** these Pug features:
|
|
99
|
+
- ❌ Logic: `if`, `else`, `unless`, `case`, `when`
|
|
100
|
+
- ❌ Loops: `each`, `while`
|
|
101
|
+
- ❌ Mixins: `mixin`, `+mixin()`
|
|
102
|
+
- ❌ Interpolation: `#{}`, `!{}`
|
|
103
|
+
|
|
104
|
+
## Why Custom Webpack?
|
|
105
|
+
|
|
106
|
+
Angular 17+ uses esbuild for speed, but esbuild plugins run **after** template validation. Custom-webpack (1.5M downloads/month) uses webpack loaders that transform templates **before** Angular processes them - the only reliable way for compile-time template transformation.
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
MIT
|
|
111
|
+
|
|
112
|
+
## Links
|
|
113
|
+
|
|
114
|
+
- **Pug**: [pugjs.org](https://pugjs.org) | [GitHub](https://github.com/pugjs/pug)
|
|
115
|
+
- **Custom Webpack**: [GitHub](https://github.com/just-jeb/angular-builders)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Puglite Angular Webpack Integration
|
|
3
|
+
*
|
|
4
|
+
* Works with @angular-builders/custom-webpack.
|
|
5
|
+
* Export a function that merges pug loader into existing webpack config.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
const loaderPath = path.resolve(__dirname, 'loader.js');
|
|
11
|
+
|
|
12
|
+
const pugRule = {
|
|
13
|
+
test: /\.pug$/,
|
|
14
|
+
use: [{ loader: loaderPath }]
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Merge function for @angular-builders/custom-webpack
|
|
19
|
+
* @param {object} config - Existing webpack configuration
|
|
20
|
+
* @returns {object} - Modified webpack configuration
|
|
21
|
+
*/
|
|
22
|
+
module.exports = (config) => {
|
|
23
|
+
config.module = config.module || {};
|
|
24
|
+
config.module.rules = config.module.rules || [];
|
|
25
|
+
config.module.rules.push(pugRule);
|
|
26
|
+
return config;
|
|
27
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webpack loader for Puglite templates
|
|
3
|
+
* Compiles .pug files to HTML at build time
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
module.exports = function pugliteLoader(source) {
|
|
7
|
+
const filename = this.resourcePath;
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
// Import puglite internal modules
|
|
11
|
+
const lex = require('../lib/lexer');
|
|
12
|
+
const parse = require('../lib/parser');
|
|
13
|
+
const generateCode = require('../lib/code-gen');
|
|
14
|
+
const stripComments = require('../lib/strip-comments');
|
|
15
|
+
const runtimeWrap = require('../lib/runtime-wrap');
|
|
16
|
+
|
|
17
|
+
// Compile: lex → parse → generate → wrap → execute
|
|
18
|
+
const tokens = lex(source, { filename });
|
|
19
|
+
const strippedTokens = stripComments(tokens, { filename });
|
|
20
|
+
const ast = parse(strippedTokens, { filename, src: source });
|
|
21
|
+
const js = generateCode(ast, {
|
|
22
|
+
compileDebug: false,
|
|
23
|
+
pretty: false,
|
|
24
|
+
inlineRuntimeFunctions: false,
|
|
25
|
+
templateName: 'template'
|
|
26
|
+
});
|
|
27
|
+
const templateFn = runtimeWrap(js);
|
|
28
|
+
const html = templateFn();
|
|
29
|
+
|
|
30
|
+
// Return as CommonJS module
|
|
31
|
+
return `module.exports = ${JSON.stringify(html)};`;
|
|
32
|
+
|
|
33
|
+
} catch (error) {
|
|
34
|
+
this.emitError(new Error(`Puglite compilation failed for ${filename}: ${error.message}`));
|
|
35
|
+
return `module.exports = "";`;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Puglite Browser Builder
|
|
3
|
+
*
|
|
4
|
+
* Wraps @angular-builders/custom-webpack browser builder and auto-injects
|
|
5
|
+
* the puglite webpack configuration for .pug template support.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { createRequire } = require('module');
|
|
10
|
+
const debug = require('util').debuglog('puglite');
|
|
11
|
+
|
|
12
|
+
const projectRequire = createRequire(path.join(process.cwd(), 'package.json'));
|
|
13
|
+
|
|
14
|
+
const loaderPath = path.resolve(__dirname, '../../angular-webpack/loader.js');
|
|
15
|
+
|
|
16
|
+
const pugRule = {
|
|
17
|
+
test: /\.pug$/,
|
|
18
|
+
use: [{ loader: loaderPath }]
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function buildBrowser(options, context) {
|
|
22
|
+
debug('buildBrowser() called');
|
|
23
|
+
const { getTransforms } = projectRequire('@angular-builders/custom-webpack');
|
|
24
|
+
const { executeBrowserBuilder } = projectRequire('@angular-devkit/build-angular');
|
|
25
|
+
|
|
26
|
+
const pugWebpackTransform = (config) => {
|
|
27
|
+
config.module = config.module || {};
|
|
28
|
+
config.module.rules = config.module.rules || [];
|
|
29
|
+
config.module.rules.push(pugRule);
|
|
30
|
+
return config;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const transforms = getTransforms(options, context);
|
|
34
|
+
const originalWebpackTransform = transforms.webpackConfiguration;
|
|
35
|
+
|
|
36
|
+
transforms.webpackConfiguration = async (config) => {
|
|
37
|
+
let result = config;
|
|
38
|
+
if (originalWebpackTransform) {
|
|
39
|
+
result = await originalWebpackTransform(result);
|
|
40
|
+
}
|
|
41
|
+
return pugWebpackTransform(result);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return executeBrowserBuilder(options, context, transforms);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const { createBuilder } = projectRequire('@angular-devkit/architect');
|
|
48
|
+
module.exports = createBuilder(buildBrowser);
|
|
49
|
+
module.exports.default = module.exports;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema",
|
|
3
|
+
"title": "Puglite Browser Builder",
|
|
4
|
+
"description": "Build browser application with Puglite template support",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"outputPath": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "The full path for the new output directory."
|
|
10
|
+
},
|
|
11
|
+
"index": {
|
|
12
|
+
"description": "Configures the generation of the application's HTML index.",
|
|
13
|
+
"oneOf": [
|
|
14
|
+
{ "type": "string" },
|
|
15
|
+
{
|
|
16
|
+
"type": "object",
|
|
17
|
+
"properties": {
|
|
18
|
+
"input": { "type": "string" },
|
|
19
|
+
"output": { "type": "string", "default": "index.html" }
|
|
20
|
+
},
|
|
21
|
+
"required": ["input"]
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"main": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"description": "The full path for the main entry point to the app."
|
|
28
|
+
},
|
|
29
|
+
"tsConfig": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"description": "The full path for the TypeScript configuration file."
|
|
32
|
+
},
|
|
33
|
+
"assets": {
|
|
34
|
+
"type": "array",
|
|
35
|
+
"description": "List of static application assets.",
|
|
36
|
+
"default": [],
|
|
37
|
+
"items": {
|
|
38
|
+
"oneOf": [
|
|
39
|
+
{ "type": "string" },
|
|
40
|
+
{
|
|
41
|
+
"type": "object",
|
|
42
|
+
"properties": {
|
|
43
|
+
"glob": { "type": "string" },
|
|
44
|
+
"input": { "type": "string" },
|
|
45
|
+
"output": { "type": "string" },
|
|
46
|
+
"ignore": { "type": "array", "items": { "type": "string" } }
|
|
47
|
+
},
|
|
48
|
+
"required": ["glob", "input"]
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"styles": {
|
|
54
|
+
"type": "array",
|
|
55
|
+
"description": "Global styles to be included in the build.",
|
|
56
|
+
"default": [],
|
|
57
|
+
"items": {
|
|
58
|
+
"oneOf": [
|
|
59
|
+
{ "type": "string" },
|
|
60
|
+
{
|
|
61
|
+
"type": "object",
|
|
62
|
+
"properties": {
|
|
63
|
+
"input": { "type": "string" },
|
|
64
|
+
"bundleName": { "type": "string" },
|
|
65
|
+
"inject": { "type": "boolean", "default": true }
|
|
66
|
+
},
|
|
67
|
+
"required": ["input"]
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"scripts": {
|
|
73
|
+
"type": "array",
|
|
74
|
+
"description": "Global scripts to be included in the build.",
|
|
75
|
+
"default": []
|
|
76
|
+
},
|
|
77
|
+
"polyfills": {
|
|
78
|
+
"description": "Polyfills to be included in the build.",
|
|
79
|
+
"oneOf": [
|
|
80
|
+
{ "type": "string" },
|
|
81
|
+
{ "type": "array", "items": { "type": "string" } }
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
"inlineStyleLanguage": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"description": "The stylesheet language to use for inline styles.",
|
|
87
|
+
"enum": ["css", "less", "sass", "scss"],
|
|
88
|
+
"default": "css"
|
|
89
|
+
},
|
|
90
|
+
"optimization": {
|
|
91
|
+
"description": "Enables optimization of the build output.",
|
|
92
|
+
"oneOf": [{ "type": "boolean" }, { "type": "object" }],
|
|
93
|
+
"default": true
|
|
94
|
+
},
|
|
95
|
+
"sourceMap": {
|
|
96
|
+
"description": "Output source maps for scripts and styles.",
|
|
97
|
+
"oneOf": [{ "type": "boolean" }, { "type": "object" }],
|
|
98
|
+
"default": false
|
|
99
|
+
},
|
|
100
|
+
"outputHashing": {
|
|
101
|
+
"type": "string",
|
|
102
|
+
"description": "Define the output filename cache-busting hashing mode.",
|
|
103
|
+
"enum": ["none", "all", "media", "bundles"],
|
|
104
|
+
"default": "none"
|
|
105
|
+
},
|
|
106
|
+
"extractLicenses": {
|
|
107
|
+
"type": "boolean",
|
|
108
|
+
"description": "Extract all licenses in a separate file.",
|
|
109
|
+
"default": true
|
|
110
|
+
},
|
|
111
|
+
"budgets": {
|
|
112
|
+
"type": "array",
|
|
113
|
+
"description": "Budget thresholds to ensure parts of your application stay within boundaries.",
|
|
114
|
+
"default": []
|
|
115
|
+
},
|
|
116
|
+
"aot": {
|
|
117
|
+
"type": "boolean",
|
|
118
|
+
"description": "Build using Ahead of Time compilation.",
|
|
119
|
+
"default": true
|
|
120
|
+
},
|
|
121
|
+
"progress": {
|
|
122
|
+
"type": "boolean",
|
|
123
|
+
"description": "Log progress to the console while building.",
|
|
124
|
+
"default": true
|
|
125
|
+
},
|
|
126
|
+
"watch": {
|
|
127
|
+
"type": "boolean",
|
|
128
|
+
"description": "Run build when files change.",
|
|
129
|
+
"default": false
|
|
130
|
+
},
|
|
131
|
+
"poll": {
|
|
132
|
+
"type": "number",
|
|
133
|
+
"description": "Enable and define the file watching poll time period in milliseconds."
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
"additionalProperties": true,
|
|
137
|
+
"required": ["outputPath", "index", "main", "tsConfig"]
|
|
138
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Puglite Dev Server Builder
|
|
3
|
+
*
|
|
4
|
+
* Wraps Angular's dev server with pug template support.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const { createRequire } = require('module');
|
|
9
|
+
const debug = require('util').debuglog('puglite');
|
|
10
|
+
|
|
11
|
+
const projectRequire = createRequire(path.join(process.cwd(), 'package.json'));
|
|
12
|
+
|
|
13
|
+
const loaderPath = path.resolve(__dirname, '../../angular-webpack/loader.js');
|
|
14
|
+
|
|
15
|
+
const pugRule = {
|
|
16
|
+
test: /\.pug$/,
|
|
17
|
+
use: [{ loader: loaderPath }]
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
function serveBrowser(options, context) {
|
|
21
|
+
debug('serveBrowser() called');
|
|
22
|
+
const { getTransforms } = projectRequire('@angular-builders/custom-webpack');
|
|
23
|
+
const { executeDevServerBuilder } = projectRequire('@angular-devkit/build-angular');
|
|
24
|
+
|
|
25
|
+
const pugWebpackTransform = (config) => {
|
|
26
|
+
config.module = config.module || {};
|
|
27
|
+
config.module.rules = config.module.rules || [];
|
|
28
|
+
config.module.rules.push(pugRule);
|
|
29
|
+
return config;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const transforms = getTransforms(options, context);
|
|
33
|
+
const originalWebpackTransform = transforms.webpackConfiguration;
|
|
34
|
+
|
|
35
|
+
transforms.webpackConfiguration = async (config) => {
|
|
36
|
+
let result = config;
|
|
37
|
+
if (originalWebpackTransform) {
|
|
38
|
+
result = await originalWebpackTransform(result);
|
|
39
|
+
}
|
|
40
|
+
return pugWebpackTransform(result);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return executeDevServerBuilder(options, context, transforms);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const { createBuilder } = projectRequire('@angular-devkit/architect');
|
|
47
|
+
module.exports = createBuilder(serveBrowser);
|
|
48
|
+
module.exports.default = module.exports;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema",
|
|
3
|
+
"title": "Puglite Dev Server Builder",
|
|
4
|
+
"description": "Development server with Puglite template support",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"buildTarget": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "A build builder target to serve in the format of `project:target[:configuration]`.",
|
|
10
|
+
"pattern": "^[^:\\s]*:[^:\\s]*(:[^\\s]+)?$"
|
|
11
|
+
},
|
|
12
|
+
"port": {
|
|
13
|
+
"type": "number",
|
|
14
|
+
"description": "Port to listen on.",
|
|
15
|
+
"default": 4200
|
|
16
|
+
},
|
|
17
|
+
"host": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "Host to listen on.",
|
|
20
|
+
"default": "localhost"
|
|
21
|
+
},
|
|
22
|
+
"proxyConfig": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "Proxy configuration file."
|
|
25
|
+
},
|
|
26
|
+
"ssl": {
|
|
27
|
+
"type": "boolean",
|
|
28
|
+
"description": "Serve using HTTPS.",
|
|
29
|
+
"default": false
|
|
30
|
+
},
|
|
31
|
+
"sslKey": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "SSL key to use for serving HTTPS."
|
|
34
|
+
},
|
|
35
|
+
"sslCert": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"description": "SSL certificate to use for serving HTTPS."
|
|
38
|
+
},
|
|
39
|
+
"headers": {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"description": "Custom HTTP headers to be added to all responses.",
|
|
42
|
+
"additionalProperties": {
|
|
43
|
+
"type": "string"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"open": {
|
|
47
|
+
"type": "boolean",
|
|
48
|
+
"description": "Opens the url in default browser.",
|
|
49
|
+
"default": false,
|
|
50
|
+
"alias": "o"
|
|
51
|
+
},
|
|
52
|
+
"verbose": {
|
|
53
|
+
"type": "boolean",
|
|
54
|
+
"description": "Adds more details to output logging."
|
|
55
|
+
},
|
|
56
|
+
"liveReload": {
|
|
57
|
+
"type": "boolean",
|
|
58
|
+
"description": "Whether to reload the page on change, using live-reload.",
|
|
59
|
+
"default": true
|
|
60
|
+
},
|
|
61
|
+
"publicHost": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"description": "The URL that the browser client should use to connect to the development server."
|
|
64
|
+
},
|
|
65
|
+
"allowedHosts": {
|
|
66
|
+
"type": "array",
|
|
67
|
+
"description": "List of hosts that are allowed to access the dev server.",
|
|
68
|
+
"default": [],
|
|
69
|
+
"items": {
|
|
70
|
+
"type": "string"
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"servePath": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"description": "The pathname where the application will be served."
|
|
76
|
+
},
|
|
77
|
+
"disableHostCheck": {
|
|
78
|
+
"type": "boolean",
|
|
79
|
+
"description": "Don't verify connected clients are part of allowed hosts.",
|
|
80
|
+
"default": false
|
|
81
|
+
},
|
|
82
|
+
"hmr": {
|
|
83
|
+
"type": "boolean",
|
|
84
|
+
"description": "Enable hot module replacement."
|
|
85
|
+
},
|
|
86
|
+
"watch": {
|
|
87
|
+
"type": "boolean",
|
|
88
|
+
"description": "Rebuild on change.",
|
|
89
|
+
"default": true
|
|
90
|
+
},
|
|
91
|
+
"poll": {
|
|
92
|
+
"type": "number",
|
|
93
|
+
"description": "Enable and define the file watching poll time period in milliseconds."
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"additionalProperties": false,
|
|
97
|
+
"required": ["buildTarget"]
|
|
98
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Puglite Karma Test Builder
|
|
2
|
+
|
|
3
|
+
Karma test runner with Puglite (`.pug`) template support for Angular projects.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
Update your `angular.json` to use the puglite karma builder:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"projects": {
|
|
12
|
+
"your-project": {
|
|
13
|
+
"architect": {
|
|
14
|
+
"test": {
|
|
15
|
+
"builder": "puglite:karma",
|
|
16
|
+
"options": {
|
|
17
|
+
"karmaConfig": "karma.conf.js",
|
|
18
|
+
"main": "src/test.ts",
|
|
19
|
+
"polyfills": ["zone.js", "zone.js/testing"],
|
|
20
|
+
"tsConfig": "tsconfig.spec.json",
|
|
21
|
+
"assets": ["src/favicon.ico", "src/assets"],
|
|
22
|
+
"styles": ["src/styles.scss"],
|
|
23
|
+
"scripts": []
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- ✅ Automatic `.pug` template loading via webpack
|
|
35
|
+
- ✅ Works with existing Karma configuration
|
|
36
|
+
- ✅ Full Angular CLI test options support
|
|
37
|
+
- ✅ Code coverage support
|
|
38
|
+
- ✅ Watch mode support
|
|
39
|
+
|
|
40
|
+
## How It Works
|
|
41
|
+
|
|
42
|
+
The builder wraps Angular's standard Karma builder and injects webpack configuration to handle `.pug` templates using the puglite loader. This allows you to:
|
|
43
|
+
|
|
44
|
+
1. Use `.pug` files as Angular component templates
|
|
45
|
+
2. Run unit tests with Karma/Jasmine
|
|
46
|
+
3. Test components that use `.pug` templates
|
|
47
|
+
|
|
48
|
+
## Example Component
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
@Component({
|
|
52
|
+
selector: 'app-example',
|
|
53
|
+
templateUrl: './example.component.pug',
|
|
54
|
+
styleUrls: ['./example.component.scss']
|
|
55
|
+
})
|
|
56
|
+
export class ExampleComponent {}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```pug
|
|
60
|
+
// example.component.pug
|
|
61
|
+
.container
|
|
62
|
+
h1 Hello World
|
|
63
|
+
p This is a pug template
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Running Tests
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
ng test
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Or with code coverage:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
ng test --code-coverage
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Requirements
|
|
79
|
+
|
|
80
|
+
- Angular 18+
|
|
81
|
+
- Karma
|
|
82
|
+
- `@angular-builders/custom-webpack` (peer dependency)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Puglite Karma Test Builder
|
|
3
|
+
*
|
|
4
|
+
* Wraps Angular's Karma test runner with pug template support.
|
|
5
|
+
* Follows @angular-builders/custom-webpack karma pattern.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { createRequire } = require('module');
|
|
10
|
+
const debug = require('util').debuglog('puglite');
|
|
11
|
+
|
|
12
|
+
const projectRequire = createRequire(path.join(process.cwd(), 'package.json'));
|
|
13
|
+
|
|
14
|
+
const loaderPath = path.resolve(__dirname, '../../angular-webpack/loader.js');
|
|
15
|
+
|
|
16
|
+
const pugRule = {
|
|
17
|
+
test: /\.pug$/,
|
|
18
|
+
use: [{ loader: loaderPath }]
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const buildKarma = (options, context) => {
|
|
22
|
+
debug('buildKarma() called');
|
|
23
|
+
const { executeKarmaBuilder } = projectRequire('@angular-devkit/build-angular');
|
|
24
|
+
|
|
25
|
+
const pugWebpackTransform = (config) => {
|
|
26
|
+
debug('applying pug webpack transform, rules: %d', (config.module?.rules?.length || 0));
|
|
27
|
+
config.module = config.module || {};
|
|
28
|
+
config.module.rules = config.module.rules || [];
|
|
29
|
+
config.module.rules.push(pugRule);
|
|
30
|
+
return config;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return executeKarmaBuilder(options, context, {
|
|
34
|
+
webpackConfiguration: pugWebpackTransform
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const { createBuilder } = projectRequire('@angular-devkit/architect');
|
|
39
|
+
module.exports = createBuilder(buildKarma);
|
|
40
|
+
module.exports.default = module.exports;
|