@baravak/risloo-profile-cli 4.46.3 → 4.75.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/.agents/skills/create-profile/SKILL.md +14 -0
- package/.claude/settings.local.json +1 -3
- package/.claude/skills/create-profile/SKILL.md +203 -0
- package/AGENTS.md +413 -0
- package/CLAUDE.md +2 -185
- package/package.json +1 -1
- package/src/cli-commands/Executor.js +8 -2
- package/src/cli-commands/ExtractExecutor.js +55 -21
- package/src/cli-commands/GiftExecutor.js +1 -0
- package/src/handlebars/importPartials.js +10 -44
- package/src/handlebars/init.js +17 -11
- package/src/publish/json/profiles/BSSI93.json +392 -0
- package/src/publish/json/profiles/FRHPT93.json +2 -2
- package/src/publish/json/profiles/ISKS93.json +288 -0
- package/src/publish/json/profiles/MCMI9A.json +1540 -0
- package/src/publish/json/profiles/NEO93.json +3858 -0
- package/src/publish/json/profiles/NEO9A.json +1159 -1
- package/src/publish/json/profiles/NEO9Q.json +3856 -0
- package/src/publish/json/profiles/NEO9V.json +1157 -0
- package/src/publish/json/profiles/RIASEC9A.json +2775 -0
- package/src/publish/json/profiles/RSI93.json +359 -0
- package/src/samples/AEQ93.js +1 -1
- package/src/samples/AMS93.js +1 -1
- package/src/samples/AMS9A.js +3 -1
- package/src/samples/BAOMEIS93.js +1 -1
- package/src/samples/BEQI93.js +1 -1
- package/src/samples/BSCT93.js +5 -0
- package/src/samples/BSSI93.js +93 -0
- package/src/samples/CAATS93.js +1 -1
- package/src/samples/CERQ93.js +1 -1
- package/src/samples/CRAAS93.js +1 -1
- package/src/samples/DSWLS93.js +1 -1
- package/src/samples/EMSS93.js +1 -1
- package/src/samples/EPQ9A.js +6 -1
- package/src/samples/FACES93.js +6 -0
- package/src/samples/FRHPT93.js +41 -13
- package/src/samples/GMIT93.js +1 -1
- package/src/samples/HPL93.js +1 -1
- package/src/samples/ISKS93.js +62 -0
- package/src/samples/IUS93.js +1 -1
- package/src/samples/JCSI93.js +1 -1
- package/src/samples/JPFQ93.js +5 -0
- package/src/samples/KJGI93.js +1 -1
- package/src/samples/LMIQ93.js +1 -1
- package/src/samples/MCMI9A.js +530 -0
- package/src/samples/MMFAD93.js +1 -1
- package/src/samples/MOCI93.js +1 -1
- package/src/samples/NEO93.js +279 -0
- package/src/samples/NEO9A.js +93 -60
- package/src/samples/NEO9Q.js +281 -0
- package/src/samples/NEO9V.js +218 -0
- package/src/samples/OBQ4493.js +1 -1
- package/src/samples/PIES93.js +1 -1
- package/src/samples/PIES9A.js +4 -0
- package/src/samples/PMCIEF93.js +7 -1
- package/src/samples/PSWQ93.js +1 -1
- package/src/samples/RIASEC93.js +1 -1
- package/src/samples/RIASEC9A.js +256 -0
- package/src/samples/RSI93.js +89 -0
- package/src/samples/SASQ93.js +1 -1
- package/src/samples/SDCAQ93.js +1 -1
- package/src/samples/STAIY93.js +1 -1
- package/src/samples/WAQ93.js +1 -1
- package/src/samples/YBOCS93.js +1 -1
- package/src/samples/YPI93.js +5 -1
- package/views/profiles/MCMI9A_facets_partial.hbs +96 -0
- package/views/profiles/MCMI9A_main_partial.hbs +262 -0
- package/views/profiles/MCMI9A_noteworthy_partial.hbs +66 -0
- package/views/profiles/MCMI9A_vertical_label_partial.hbs +8 -0
- package/views/profiles/NEO_long_facets.hbs +125 -0
- package/views/profiles/NEO_main.hbs +152 -0
- package/views/profiles/NEO_short_facets.hbs +82 -0
- package/views/profiles/samples/BSCT93.hbs +17 -17
- package/views/profiles/samples/BSSI93.hbs +102 -0
- package/views/profiles/samples/FRHPT93_1.hbs +568 -87
- package/views/profiles/samples/FRHPT93_2.hbs +90 -76
- package/views/profiles/samples/FRHPT93_3.hbs +2 -2
- package/views/profiles/samples/FRHPT93_4.hbs +2 -2
- package/views/profiles/samples/FRHPT93_5.hbs +103 -0
- package/views/profiles/samples/FRHPT9A.hbs +7 -7
- package/views/profiles/samples/ISKS93.hbs +38 -0
- package/views/profiles/samples/MCMI9A_1.hbs +3 -0
- package/views/profiles/samples/MCMI9A_2.hbs +3 -0
- package/views/profiles/samples/MCMI9A_3.hbs +3 -0
- package/views/profiles/samples/MCMI9A_4.hbs +3 -0
- package/views/profiles/samples/NEO93_1.hbs +14 -0
- package/views/profiles/samples/NEO93_2.hbs +15 -0
- package/views/profiles/samples/NEO93_3.hbs +15 -0
- package/views/profiles/samples/NEO9A.hbs +14 -29
- package/views/profiles/samples/NEO9Q_1.hbs +13 -0
- package/views/profiles/samples/NEO9Q_2.hbs +14 -0
- package/views/profiles/samples/NEO9Q_3.hbs +14 -0
- package/views/profiles/samples/NEO9V_1.hbs +13 -0
- package/views/profiles/samples/NEO9V_2.hbs +3 -0
- package/views/profiles/samples/RIASEC9A_1.hbs +38 -0
- package/views/profiles/samples/RIASEC9A_2.hbs +67 -0
- package/views/profiles/samples/RIASEC9A_3.hbs +93 -0
- package/views/profiles/samples/RSI93.hbs +101 -0
- package/a.json +0 -4805
- package/src/publish/json/profiles/BSCT93_t1.json +0 -512
- package/src/publish/json/profiles/BSCT93_t2.json +0 -512
package/CLAUDE.md
CHANGED
|
@@ -1,188 +1,5 @@
|
|
|
1
1
|
# CLAUDE.md
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Pointer only — all project instructions live in [AGENTS.md](AGENTS.md). Edit that file, not this one.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Published as npm package: `@baravak/risloo-profile-cli` (v4.46.2, MIT)
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## Directory Structure
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
risloo-extractor-app/
|
|
15
|
-
├── bin/
|
|
16
|
-
│ └── risloo.js # CLI entry point
|
|
17
|
-
├── src/
|
|
18
|
-
│ ├── cli.js # Commander.js command definitions
|
|
19
|
-
│ ├── cli-commands/
|
|
20
|
-
│ │ ├── Executor.js # Base executor class
|
|
21
|
-
│ │ ├── ExtractExecutor.js # Profile/report/sheet extraction logic
|
|
22
|
-
│ │ ├── GiftExecutor.js # Gift card generation
|
|
23
|
-
│ │ └── utilities/ # BaseOps, Benchmarker, Response, Errors, Status codes
|
|
24
|
-
│ ├── Profile.js # Base Profile class (math utilities)
|
|
25
|
-
│ ├── Gift.js # Gift card class
|
|
26
|
-
│ ├── samples/ # JS controller files — one per profile (e.g. BSCT93.js)
|
|
27
|
-
│ ├── handlebars/
|
|
28
|
-
│ │ ├── init.js # Handlebars initialization
|
|
29
|
-
│ │ ├── helpers.js # Entry point for all helpers
|
|
30
|
-
│ │ ├── helpers/ # 45+ geometry helper modules
|
|
31
|
-
│ │ ├── importPartials.js # Partials loader
|
|
32
|
-
│ │ └── polygon.js # Polygon drawing logic
|
|
33
|
-
│ ├── helpers/ # Math helpers (angleABS, polarXY, gauge, polygonXY)
|
|
34
|
-
│ ├── qrcode/ # QR code generation & rendering
|
|
35
|
-
│ └── publish/
|
|
36
|
-
│ ├── json/profiles/ # Template JSON per sample (e.g. BSCT93.json)
|
|
37
|
-
│ ├── json/gift/ # Gift template data
|
|
38
|
-
│ ├── test.js # Auto-test all samples
|
|
39
|
-
│ └── bot.js # Post-publish automation
|
|
40
|
-
├── views/
|
|
41
|
-
│ ├── profiles/samples/ # Handlebars SVG templates (.hbs)
|
|
42
|
-
│ └── gift.hbs
|
|
43
|
-
└── package.json
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
## Commands
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
# Test a single profile (generates SVG in ./temp)
|
|
52
|
-
./bin/risloo.js E <NAME> -d ./src/publish/json/profiles/<NAME>.json -a ./temp
|
|
53
|
-
|
|
54
|
-
# Watch mode
|
|
55
|
-
risloo extract <NAME> profile -i local -d ./src/publish/json/profiles/<NAME>.json -o local -a ./temp -w
|
|
56
|
-
|
|
57
|
-
# Generate gift card
|
|
58
|
-
risloo gift -i raw-json -d '{"code":"..."}' -o local -a ./output
|
|
59
|
-
|
|
60
|
-
# Test all samples
|
|
61
|
-
npm test # → node ./src/publish/test.js
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
---
|
|
65
|
-
|
|
66
|
-
## Profile Development Workflow (Figma → Code)
|
|
67
|
-
|
|
68
|
-
### Design Source
|
|
69
|
-
|
|
70
|
-
Each profile is designed in Figma. Per task, one or both of the following may be provided:
|
|
71
|
-
|
|
72
|
-
- **Figma design file** — connect via Figma MCP to read layer dimensions and structure. The relevant layer is named **Chart**.
|
|
73
|
-
- **Figma handoff file** — contains additional implementation notes and specs. May state that this profile is similar to an existing one (e.g. "similar to BSCT93 with these changes"). In that case: find the referenced profile's JS + HBS files, use them as the base, and apply only the described differences.
|
|
74
|
-
|
|
75
|
-
> **Important:** The Figma MCP reads text layers only — it does NOT read Figma comments. Designers often leave critical specs (thresholds, coefficients, pixel values) as Figma comments. Always ask the user to share designer comments before finalizing the plan.
|
|
76
|
-
|
|
77
|
-
### What the HBS Draws
|
|
78
|
-
|
|
79
|
-
The HBS file draws **only the Chart layer**. The library automatically injects the header (test name, dates, client info) and sidebar (logo, room info, prerequisites) via the `{{#> layout}}` wrapper. Never include these in the HBS.
|
|
80
|
-
|
|
81
|
-
### SVG Coordinate System
|
|
82
|
-
|
|
83
|
-
Since this is SVG, coordinate origin matters for correctness across **all** inputs:
|
|
84
|
-
|
|
85
|
-
- **x=0** = left edge, increases rightward
|
|
86
|
-
- **y=0** = top edge, increases downward
|
|
87
|
-
- Horizontal bars fill left → right: `{{bar (BAR_WIDTH * factor.p) height ...}}`
|
|
88
|
-
- Vertical total bar fills bottom → up via the transform trick: `translate(0, barHeight - barHeight * p)`
|
|
89
|
-
- All positions must remain stable for edge-case inputs: 0% score, 100% score, missing data
|
|
90
|
-
|
|
91
|
-
### Inside/Outside Bar Text
|
|
92
|
-
|
|
93
|
-
When rendering percentage text on a bar, check if the bar is wide enough to contain the text. The threshold is specified by the designer per profile (in Figma comments):
|
|
94
|
-
|
|
95
|
-
```hbs
|
|
96
|
-
{{#if (boolean factor.percentage '<=' THRESHOLD)}}
|
|
97
|
-
<text x="{{math (math BAR_WIDTH '*' factor.p) '+' 6}}" ...>{{factor.percentage}} ٪</text>
|
|
98
|
-
{{else}}
|
|
99
|
-
<text x="{{math (math BAR_WIDTH '*' factor.p) '-' 4}}" ...>{{factor.percentage}} ٪</text>
|
|
100
|
-
{{/if}}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### File Structure per Profile
|
|
104
|
-
|
|
105
|
-
Each profile (نیمرخ) consists of three files:
|
|
106
|
-
|
|
107
|
-
| File | Path | Role |
|
|
108
|
-
|---|---|---|
|
|
109
|
-
| JSON template | `src/publish/json/profiles/<NAME>.json` | Test data / input template |
|
|
110
|
-
| JS controller | `src/samples/<NAME>.js` | Data processing, geometry config |
|
|
111
|
-
| HBS template | `views/profiles/samples/<NAME>.hbs` | SVG rendering |
|
|
112
|
-
|
|
113
|
-
If a profile has **multiple pages**, the HBS files are named with suffixes:
|
|
114
|
-
- `<NAME>_1.hbs`, `<NAME>_2.hbs`, `<NAME>_3.hbs`, ...
|
|
115
|
-
|
|
116
|
-
### Dimensions & Padding Convention
|
|
117
|
-
|
|
118
|
-
The chart drawing must fit within the **Main** layer in Figma.
|
|
119
|
-
|
|
120
|
-
- Read the **Main** layer dimensions from Figma
|
|
121
|
-
- `profile.padding` = 20 units per side
|
|
122
|
-
- The `x` and `y` values (drawing area) = Main dimensions minus one padding unit each:
|
|
123
|
-
- e.g. Main = 104×255 → `{ x: 84, y: 235 }`
|
|
124
|
-
|
|
125
|
-
The `dimensions` property in the JS controller adds padding back on both sides of the **Chart** layer dimensions:
|
|
126
|
-
|
|
127
|
-
```js
|
|
128
|
-
get dimensions() {
|
|
129
|
-
return {
|
|
130
|
-
width: 736 + 2 * this.padding.x, // Chart layer width from Figma
|
|
131
|
-
height: 254 + 2 * this.padding.y, // Chart layer height from Figma
|
|
132
|
-
};
|
|
133
|
-
},
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### Data / Labels Convention
|
|
137
|
-
|
|
138
|
-
All data needed for rendering goes in the `labels` property of the JS controller.
|
|
139
|
-
|
|
140
|
-
The data structure is typically derived from a Python script that outputs a JSON file — flattened with `_` separators — which maps source fields to their `labels` keys.
|
|
141
|
-
|
|
142
|
-
```js
|
|
143
|
-
get labels() {
|
|
144
|
-
return {
|
|
145
|
-
// flat_key: value
|
|
146
|
-
score_total: ...,
|
|
147
|
-
subscale_anxiety: ...,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
---
|
|
153
|
-
|
|
154
|
-
## Tech Stack
|
|
155
|
-
|
|
156
|
-
| Area | Technology |
|
|
157
|
-
|---|---|
|
|
158
|
-
| Language | JavaScript (Node.js, no build step) |
|
|
159
|
-
| CLI | Commander.js |
|
|
160
|
-
| Templating | Handlebars (SVG generation) |
|
|
161
|
-
| Image output | Sharp (SVG → PNG) |
|
|
162
|
-
| Dates | Moment.js + moment-jalaali (Persian calendar) |
|
|
163
|
-
| QR codes | qrcode |
|
|
164
|
-
| File watching | Chokidar |
|
|
165
|
-
| Package manager | Yarn |
|
|
166
|
-
| Design source | Figma (via MCP) |
|
|
167
|
-
|
|
168
|
-
---
|
|
169
|
-
|
|
170
|
-
## Naming Conventions
|
|
171
|
-
|
|
172
|
-
- `items` — array of data elements to draw
|
|
173
|
-
- `raw` — total/aggregate element
|
|
174
|
-
- `ticks` — graduation marks on profiles
|
|
175
|
-
- `s` suffix — denotes arrays (not `Arr`)
|
|
176
|
-
- Sample names: uppercase acronym + year (e.g. `BSCT93`, `BEQI93`, `16PF93`)
|
|
177
|
-
- Dataset score structure: `dataset.score = [{ label: { eng, ... }, mark }]`
|
|
178
|
-
|
|
179
|
-
---
|
|
180
|
-
|
|
181
|
-
## Publishing
|
|
182
|
-
|
|
183
|
-
```bash
|
|
184
|
-
npm version <patch|minor|major>
|
|
185
|
-
npm publish
|
|
186
|
-
# prepublishOnly: npm test
|
|
187
|
-
# postpublish: npm run bot
|
|
188
|
-
```
|
|
5
|
+
@AGENTS.md
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { checkAndLoad, loadStdin, ensureDirExistence, createSVG, createPNG } = require("./utilities/BaseOps");
|
|
2
|
-
const
|
|
2
|
+
const createHandlebars = require("../handlebars/init");
|
|
3
3
|
const path = require("path");
|
|
4
4
|
const Benchmarker = require("./utilities/Benchmarker");
|
|
5
5
|
const Response = require("./utilities/Response");
|
|
@@ -74,8 +74,14 @@ class Executor {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
_addHandlebarsPromise(partials = {}) {
|
|
78
|
+
this.promises["handlebars"] = Promise.resolve(partials).then(createHandlebars);
|
|
79
|
+
return this.promises["handlebars"];
|
|
80
|
+
}
|
|
81
|
+
|
|
77
82
|
async _renderTemplate(ctx, templateBuffer) {
|
|
78
|
-
const
|
|
83
|
+
const hbs = await this.promises.handlebars;
|
|
84
|
+
const template = hbs.compile(templateBuffer.toString(), "utf-8");
|
|
79
85
|
return template(ctx);
|
|
80
86
|
}
|
|
81
87
|
|
|
@@ -7,7 +7,8 @@ const { FileNotFoundError } = require("./utilities/CustomErrors");
|
|
|
7
7
|
|
|
8
8
|
class ExtractExecutor extends Executor {
|
|
9
9
|
samplesJSDir = path.join(__dirname, "..", "samples");
|
|
10
|
-
|
|
10
|
+
profilesDir = path.join(__dirname, "..", "..", "views", "profiles");
|
|
11
|
+
profilesTemplatesDir = path.join(this.profilesDir, "samples");
|
|
11
12
|
|
|
12
13
|
constructor(options) {
|
|
13
14
|
super(options);
|
|
@@ -39,6 +40,18 @@ class ExtractExecutor extends Executor {
|
|
|
39
40
|
});
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
_addProfileHandlebarsPromise() {
|
|
44
|
+
const { promises, response } = this;
|
|
45
|
+
const partials = promises["js"].then((Profile) => Profile.partials || {});
|
|
46
|
+
const handlebarsPromise = this._addHandlebarsPromise(partials);
|
|
47
|
+
|
|
48
|
+
promises["handlebars"] = handlebarsPromise.catch((err) =>
|
|
49
|
+
response.setStatus(EXTRACT_STATUS["TEMPLATE_NOT_FOUND"], err)
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return promises["handlebars"];
|
|
53
|
+
}
|
|
54
|
+
|
|
42
55
|
_addProfilesTemplatePromises() {
|
|
43
56
|
const { sample, dirs, profilesTemplatesDir, promises, response } = this;
|
|
44
57
|
|
|
@@ -77,6 +90,7 @@ class ExtractExecutor extends Executor {
|
|
|
77
90
|
name: options.name,
|
|
78
91
|
};
|
|
79
92
|
|
|
93
|
+
this._addProfileHandlebarsPromise();
|
|
80
94
|
this._addProfilesTemplatePromises();
|
|
81
95
|
}
|
|
82
96
|
|
|
@@ -124,7 +138,7 @@ class ExtractExecutor extends Executor {
|
|
|
124
138
|
}
|
|
125
139
|
|
|
126
140
|
_watch() {
|
|
127
|
-
const {
|
|
141
|
+
const { dirs, input, promises } = this;
|
|
128
142
|
|
|
129
143
|
const opts = {
|
|
130
144
|
awaitWriteFinish: {
|
|
@@ -137,38 +151,58 @@ class ExtractExecutor extends Executor {
|
|
|
137
151
|
dirs.templates.map((templateFileDir, index) => {
|
|
138
152
|
chokidar.watch(templateFileDir, opts).on("change", () => {
|
|
139
153
|
promises["templates"][index] = checkAndLoad(templateFileDir);
|
|
140
|
-
|
|
141
|
-
this._createProfile("with-sidebar", ["svg"]).then(() => {
|
|
142
|
-
benchmarker?.end();
|
|
143
|
-
response.setTime(benchmarker?.totalTime);
|
|
144
|
-
response.showOutput();
|
|
145
|
-
});
|
|
154
|
+
this._renderWatchedProfile();
|
|
146
155
|
});
|
|
147
156
|
});
|
|
148
157
|
});
|
|
149
158
|
|
|
159
|
+
this._resetPartialWatcher(opts).catch(() => {});
|
|
160
|
+
|
|
150
161
|
chokidar.watch(dirs.sampleJS, opts).on("change", () => {
|
|
151
162
|
promises["js"] = checkAndImport(dirs.sampleJS);
|
|
152
|
-
|
|
153
|
-
this.
|
|
154
|
-
|
|
155
|
-
response.setTime(benchmarker?.totalTime);
|
|
156
|
-
response.showOutput();
|
|
157
|
-
});
|
|
163
|
+
this._addProfileHandlebarsPromise();
|
|
164
|
+
this._resetPartialWatcher(opts).catch(() => {});
|
|
165
|
+
this._renderWatchedProfile();
|
|
158
166
|
});
|
|
159
167
|
|
|
160
168
|
if(input.type === 'local') chokidar.watch(input.data, opts).on('change', () => {
|
|
161
169
|
promises["input"] = checkAndLoad(input.data).then((json) => Promise.resolve(JSON.parse(json)));
|
|
162
|
-
|
|
163
|
-
this._createProfile("with-sidebar", ["svg"]).then(() => {
|
|
164
|
-
benchmarker?.end();
|
|
165
|
-
response.setTime(benchmarker?.totalTime);
|
|
166
|
-
response.showOutput();
|
|
167
|
-
});
|
|
168
|
-
|
|
170
|
+
this._renderWatchedProfile();
|
|
169
171
|
})
|
|
170
172
|
}
|
|
171
173
|
|
|
174
|
+
async _resetPartialWatcher(opts) {
|
|
175
|
+
const { dirs, profilesDir, promises } = this;
|
|
176
|
+
const Profile = await promises["js"];
|
|
177
|
+
const partialDirs = Object.values(Profile.partials || {}).map((partialFile) =>
|
|
178
|
+
path.join(profilesDir, partialFile)
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
dirs["partials"] = partialDirs;
|
|
182
|
+
|
|
183
|
+
if (this.partialWatcher) await this.partialWatcher.close();
|
|
184
|
+
if (!partialDirs.length) {
|
|
185
|
+
this.partialWatcher = null;
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
this.partialWatcher = chokidar.watch(partialDirs, opts).on("change", () => {
|
|
190
|
+
this._addProfileHandlebarsPromise();
|
|
191
|
+
this._renderWatchedProfile();
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
_renderWatchedProfile() {
|
|
196
|
+
const { command, response, benchmarker } = this;
|
|
197
|
+
|
|
198
|
+
benchmarker?.restart(command);
|
|
199
|
+
return this._createProfile("with-sidebar", ["svg"]).then(() => {
|
|
200
|
+
benchmarker?.end();
|
|
201
|
+
response.setTime(benchmarker?.totalTime);
|
|
202
|
+
response.showOutput();
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
172
206
|
_createProfileOutputName(variant) {
|
|
173
207
|
const {
|
|
174
208
|
settings: {
|
|
@@ -1,51 +1,17 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const { readdir } = require("fs/promises");
|
|
1
|
+
const fs = require("fs/promises");
|
|
3
2
|
const path = require("path");
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
const baseProfiles = [
|
|
7
|
-
"AMS93",
|
|
8
|
-
"MMFAD93",
|
|
9
|
-
"PIES93",
|
|
10
|
-
"JPFQ93_partial",
|
|
11
|
-
"JPFQ93_partial2",
|
|
12
|
-
"FACES93_1_partial",
|
|
13
|
-
"FACES93_2_1_partial",
|
|
14
|
-
"FACES93_2_2_partial",
|
|
15
|
-
"EPQ93",
|
|
16
|
-
'YPI93_factors'
|
|
17
|
-
];
|
|
4
|
+
const partialsDir = path.join(__dirname, "..", "..", "views", "profiles");
|
|
18
5
|
|
|
19
|
-
async function importPartials(hbs) {
|
|
20
|
-
|
|
6
|
+
async function importPartials(hbs, partials) {
|
|
7
|
+
await Promise.all(
|
|
8
|
+
Object.entries(partials).map(async ([name, relativePath]) => {
|
|
9
|
+
const template = await fs.readFile(path.join(partialsDir, relativePath), "utf-8");
|
|
10
|
+
hbs.registerPartial(name, template);
|
|
11
|
+
})
|
|
12
|
+
);
|
|
21
13
|
|
|
22
|
-
|
|
23
|
-
new Promise(function (resolve, reject) {
|
|
24
|
-
fs.readFile(path.join(partialsDir, "samples", `${profileName}.hbs`), "utf-8", (err, template) => {
|
|
25
|
-
if (err) reject(err);
|
|
26
|
-
hbs.registerPartial(profileName, template);
|
|
27
|
-
resolve(true);
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
return readdir(partialsDir).then((partialFiles) => {
|
|
33
|
-
let generalPartialsPromises = partialFiles.map(
|
|
34
|
-
(partialFile) =>
|
|
35
|
-
new Promise(function (resolve, reject) {
|
|
36
|
-
const matches = /^([^.]+).(hbs|css|js)$/.exec(partialFile);
|
|
37
|
-
if (!matches) return resolve(true);
|
|
38
|
-
const name = matches[1];
|
|
39
|
-
fs.readFile(path.join(partialsDir, partialFile), "utf-8", (err, template) => {
|
|
40
|
-
if (err) reject(err);
|
|
41
|
-
hbs.registerPartial(name, template);
|
|
42
|
-
resolve(true);
|
|
43
|
-
});
|
|
44
|
-
})
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
return Promise.all(generalPartialsPromises, baseProfilePromises);
|
|
48
|
-
});
|
|
14
|
+
return hbs;
|
|
49
15
|
}
|
|
50
16
|
|
|
51
17
|
module.exports = importPartials;
|
package/src/handlebars/init.js
CHANGED
|
@@ -2,14 +2,20 @@ const Handlebars = require("handlebars");
|
|
|
2
2
|
const helpers = require("./helpers");
|
|
3
3
|
const importPartials = require("./importPartials");
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
const sharedPartials = {
|
|
6
|
+
fonts: "fonts.css",
|
|
7
|
+
layout: "layout.hbs",
|
|
8
|
+
sidebar: "sidebar.hbs",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
async function createHandlebars(partials = {}) {
|
|
12
|
+
const hbs = Handlebars.create();
|
|
13
|
+
|
|
14
|
+
for (const [name, helper] of Object.entries(helpers)) {
|
|
15
|
+
hbs.registerHelper(name, helper);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return importPartials(hbs, { ...partials, ...sharedPartials });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = createHandlebars;
|