mirror of
https://github.com/morten-olsen/http.md.git
synced 2026-02-08 00:46:28 +01:00
feat: add javascript code block support (#13)
This commit is contained in:
@@ -211,7 +211,7 @@ _(Note: `httpbin.org/post` wraps the JSON sent in a "json" field in its response
|
|||||||
GET https://httpbin.org/status/201
|
GET https://httpbin.org/status/201
|
||||||
```
|
```
|
||||||
|
|
||||||
The request to `/status/201` completed with status code: **{{response.status}}**.
|
The request to `/status/201` completed with status code: **{{{response.status}}}**.
|
||||||
````
|
````
|
||||||
|
|
||||||
## Managing Documents
|
## Managing Documents
|
||||||
@@ -259,8 +259,8 @@ http.md build mydoc.md output.md -i baseUrl=https://api.production.example.com -
|
|||||||
|
|
||||||
````markdown
|
````markdown
|
||||||
```http
|
```http
|
||||||
GET {{input.baseUrl}}/users/1
|
GET {{{input.baseUrl}}}/users/1
|
||||||
Authorization: Bearer {{input.apiKey}}
|
Authorization: Bearer {{{input.apiKey}}}
|
||||||
```
|
```
|
||||||
|
|
||||||
::response
|
::response
|
||||||
@@ -268,6 +268,33 @@ Authorization: Bearer {{input.apiKey}}
|
|||||||
|
|
||||||
**Security Note:** For sensitive data like API keys, using input variables is highly recommended over hardcoding them in your markdown files. Avoid committing files with plaintext secrets; instead, provide them at runtime via the CLI.
|
**Security Note:** For sensitive data like API keys, using input variables is highly recommended over hardcoding them in your markdown files. Avoid committing files with plaintext secrets; instead, provide them at runtime via the CLI.
|
||||||
|
|
||||||
|
### JavaScript Execution
|
||||||
|
|
||||||
|
You can execute `javascript` blocks by adding a `run` option which allows programmatically changing the context, making request assertions and solve other more advanced use cases
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
::raw-md[./examples/with-javascript.md]
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Output</summary>
|
||||||
|
|
||||||
|
::raw-md[./examples/with-javascript.md]{render}
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
**Options:**
|
||||||
|
|
||||||
|
- `run`: If present the code block will be executed
|
||||||
|
|
||||||
|
- Example: ` ```javascript run `
|
||||||
|
|
||||||
|
- `hidden`: If present the code block will not be included in the resulting output
|
||||||
|
|
||||||
|
- Example: ` ```javascript hidden `
|
||||||
|
|
||||||
|
- `output`: If present the code blocks return value will be rendered as a `yaml` code block
|
||||||
|
|
||||||
### HTTP Block Configuration Options
|
### HTTP Block Configuration Options
|
||||||
|
|
||||||
You can configure the behavior of each `http` code block by adding options to its info string, separated by commas.
|
You can configure the behavior of each `http` code block by adding options to its info string, separated by commas.
|
||||||
@@ -309,8 +336,8 @@ You can configure the behavior of each `http` code block by adding options to it
|
|||||||
|
|
||||||
````markdown
|
````markdown
|
||||||
```http id=complexRequest,json,yaml,hidden
|
```http id=complexRequest,json,yaml,hidden
|
||||||
POST {{input.apiEndpoint}}/data
|
POST {{{input.apiEndpoint}}}/data
|
||||||
X-API-Key: {{input.apiKey}}
|
X-API-Key: {{{input.apiKey}}}
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
# Request body written in YAML, will be converted to JSON
|
# Request body written in YAML, will be converted to JSON
|
||||||
|
|||||||
17
docs/examples/with-javascript.md
Normal file
17
docs/examples/with-javascript.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
```javascript run
|
||||||
|
input.test = "Hello World";
|
||||||
|
```
|
||||||
|
|
||||||
|
::input[test]
|
||||||
|
|
||||||
|
```http json
|
||||||
|
POST https://httpbin.org/post
|
||||||
|
|
||||||
|
{"input": "{{input.test}}"}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript run,hidden
|
||||||
|
// Use chai's `expect`, `assert` or `should` to make assumptions
|
||||||
|
expect(response.body.json.input).to.equal("Hello World");
|
||||||
|
```
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@pnpm/find-workspace-packages": "^6.0.9",
|
"@pnpm/find-workspace-packages": "^6.0.9",
|
||||||
"@types/blessed": "^0.1.25",
|
"@types/blessed": "^0.1.25",
|
||||||
|
"@types/chai": "^5.2.2",
|
||||||
"@types/marked-terminal": "^6.1.1",
|
"@types/marked-terminal": "^6.1.1",
|
||||||
"@types/mdast": "^4.0.4",
|
"@types/mdast": "^4.0.4",
|
||||||
"@types/node": "^22.15.18",
|
"@types/node": "^22.15.18",
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"blessed": "^0.1.81",
|
"blessed": "^0.1.81",
|
||||||
|
"chai": "^5.2.0",
|
||||||
"chalk": "^5.4.1",
|
"chalk": "^5.4.1",
|
||||||
"commander": "^14.0.0",
|
"commander": "^14.0.0",
|
||||||
"dotenv": "^16.5.0",
|
"dotenv": "^16.5.0",
|
||||||
|
|||||||
59
pnpm-lock.yaml
generated
59
pnpm-lock.yaml
generated
@@ -11,6 +11,9 @@ importers:
|
|||||||
blessed:
|
blessed:
|
||||||
specifier: ^0.1.81
|
specifier: ^0.1.81
|
||||||
version: 0.1.81
|
version: 0.1.81
|
||||||
|
chai:
|
||||||
|
specifier: ^5.2.0
|
||||||
|
version: 5.2.0
|
||||||
chalk:
|
chalk:
|
||||||
specifier: ^5.4.1
|
specifier: ^5.4.1
|
||||||
version: 5.4.1
|
version: 5.4.1
|
||||||
@@ -84,6 +87,9 @@ importers:
|
|||||||
'@types/blessed':
|
'@types/blessed':
|
||||||
specifier: ^0.1.25
|
specifier: ^0.1.25
|
||||||
version: 0.1.25
|
version: 0.1.25
|
||||||
|
'@types/chai':
|
||||||
|
specifier: ^5.2.2
|
||||||
|
version: 5.2.2
|
||||||
'@types/marked-terminal':
|
'@types/marked-terminal':
|
||||||
specifier: ^6.1.1
|
specifier: ^6.1.1
|
||||||
version: 6.1.1
|
version: 6.1.1
|
||||||
@@ -437,9 +443,15 @@ packages:
|
|||||||
'@types/cardinal@2.1.1':
|
'@types/cardinal@2.1.1':
|
||||||
resolution: {integrity: sha512-/xCVwg8lWvahHsV2wXZt4i64H1sdL+sN1Uoq7fAc8/FA6uYHjuIveDwPwvGUYp4VZiv85dVl6J/Bum3NDAOm8g==}
|
resolution: {integrity: sha512-/xCVwg8lWvahHsV2wXZt4i64H1sdL+sN1Uoq7fAc8/FA6uYHjuIveDwPwvGUYp4VZiv85dVl6J/Bum3NDAOm8g==}
|
||||||
|
|
||||||
|
'@types/chai@5.2.2':
|
||||||
|
resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==}
|
||||||
|
|
||||||
'@types/debug@4.1.12':
|
'@types/debug@4.1.12':
|
||||||
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
|
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
|
||||||
|
|
||||||
|
'@types/deep-eql@4.0.2':
|
||||||
|
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
|
||||||
|
|
||||||
'@types/hast@3.0.4':
|
'@types/hast@3.0.4':
|
||||||
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
|
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
|
||||||
|
|
||||||
@@ -522,6 +534,10 @@ packages:
|
|||||||
as-table@1.0.55:
|
as-table@1.0.55:
|
||||||
resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==}
|
resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==}
|
||||||
|
|
||||||
|
assertion-error@2.0.1:
|
||||||
|
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
bail@2.0.2:
|
bail@2.0.2:
|
||||||
resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
|
resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
|
||||||
|
|
||||||
@@ -564,6 +580,10 @@ packages:
|
|||||||
ccount@2.0.1:
|
ccount@2.0.1:
|
||||||
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
|
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
|
||||||
|
|
||||||
|
chai@5.2.0:
|
||||||
|
resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
chalk@4.1.2:
|
chalk@4.1.2:
|
||||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -588,6 +608,10 @@ packages:
|
|||||||
character-reference-invalid@2.0.1:
|
character-reference-invalid@2.0.1:
|
||||||
resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
|
resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
|
||||||
|
|
||||||
|
check-error@2.1.1:
|
||||||
|
resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
|
||||||
|
engines: {node: '>= 16'}
|
||||||
|
|
||||||
chroma-js@2.6.0:
|
chroma-js@2.6.0:
|
||||||
resolution: {integrity: sha512-BLHvCB9s8Z1EV4ethr6xnkl/P2YRFOGqfgvuMG/MyCbZPrTA+NeiByY6XvgF0zP4/2deU2CXnWyMa3zu1LqQ3A==}
|
resolution: {integrity: sha512-BLHvCB9s8Z1EV4ethr6xnkl/P2YRFOGqfgvuMG/MyCbZPrTA+NeiByY6XvgF0zP4/2deU2CXnWyMa3zu1LqQ3A==}
|
||||||
|
|
||||||
@@ -658,6 +682,10 @@ packages:
|
|||||||
decode-named-character-reference@1.1.0:
|
decode-named-character-reference@1.1.0:
|
||||||
resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==}
|
resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==}
|
||||||
|
|
||||||
|
deep-eql@5.0.2:
|
||||||
|
resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
defaults@1.0.4:
|
defaults@1.0.4:
|
||||||
resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
|
resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
|
||||||
|
|
||||||
@@ -911,6 +939,9 @@ packages:
|
|||||||
longest-streak@3.1.0:
|
longest-streak@3.1.0:
|
||||||
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
|
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
|
||||||
|
|
||||||
|
loupe@3.1.3:
|
||||||
|
resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==}
|
||||||
|
|
||||||
map-age-cleaner@0.1.3:
|
map-age-cleaner@0.1.3:
|
||||||
resolution: {integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==}
|
resolution: {integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -1194,6 +1225,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-cMMJTAZlion/RWRRC48UbrDymEIt+/YSD/l8NqjneyDw2rDOBQcP5yRkMB4CYGn47KMhZvbblBP7Z79OsMw72w==}
|
resolution: {integrity: sha512-cMMJTAZlion/RWRRC48UbrDymEIt+/YSD/l8NqjneyDw2rDOBQcP5yRkMB4CYGn47KMhZvbblBP7Z79OsMw72w==}
|
||||||
engines: {node: '>=8.15'}
|
engines: {node: '>=8.15'}
|
||||||
|
|
||||||
|
pathval@2.0.0:
|
||||||
|
resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==}
|
||||||
|
engines: {node: '>= 14.16'}
|
||||||
|
|
||||||
picocolors@1.1.1:
|
picocolors@1.1.1:
|
||||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||||
|
|
||||||
@@ -1916,10 +1951,16 @@ snapshots:
|
|||||||
|
|
||||||
'@types/cardinal@2.1.1': {}
|
'@types/cardinal@2.1.1': {}
|
||||||
|
|
||||||
|
'@types/chai@5.2.2':
|
||||||
|
dependencies:
|
||||||
|
'@types/deep-eql': 4.0.2
|
||||||
|
|
||||||
'@types/debug@4.1.12':
|
'@types/debug@4.1.12':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/ms': 2.1.0
|
'@types/ms': 2.1.0
|
||||||
|
|
||||||
|
'@types/deep-eql@4.0.2': {}
|
||||||
|
|
||||||
'@types/hast@3.0.4':
|
'@types/hast@3.0.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 3.0.3
|
'@types/unist': 3.0.3
|
||||||
@@ -2000,6 +2041,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
printable-characters: 1.0.42
|
printable-characters: 1.0.42
|
||||||
|
|
||||||
|
assertion-error@2.0.1: {}
|
||||||
|
|
||||||
bail@2.0.2: {}
|
bail@2.0.2: {}
|
||||||
|
|
||||||
better-path-resolve@1.0.0:
|
better-path-resolve@1.0.0:
|
||||||
@@ -2044,6 +2087,14 @@ snapshots:
|
|||||||
|
|
||||||
ccount@2.0.1: {}
|
ccount@2.0.1: {}
|
||||||
|
|
||||||
|
chai@5.2.0:
|
||||||
|
dependencies:
|
||||||
|
assertion-error: 2.0.1
|
||||||
|
check-error: 2.1.1
|
||||||
|
deep-eql: 5.0.2
|
||||||
|
loupe: 3.1.3
|
||||||
|
pathval: 2.0.0
|
||||||
|
|
||||||
chalk@4.1.2:
|
chalk@4.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-styles: 4.3.0
|
ansi-styles: 4.3.0
|
||||||
@@ -2061,6 +2112,8 @@ snapshots:
|
|||||||
|
|
||||||
character-reference-invalid@2.0.1: {}
|
character-reference-invalid@2.0.1: {}
|
||||||
|
|
||||||
|
check-error@2.1.1: {}
|
||||||
|
|
||||||
chroma-js@2.6.0: {}
|
chroma-js@2.6.0: {}
|
||||||
|
|
||||||
cli-boxes@2.2.1: {}
|
cli-boxes@2.2.1: {}
|
||||||
@@ -2130,6 +2183,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
character-entities: 2.0.2
|
character-entities: 2.0.2
|
||||||
|
|
||||||
|
deep-eql@5.0.2: {}
|
||||||
|
|
||||||
defaults@1.0.4:
|
defaults@1.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
clone: 1.0.4
|
clone: 1.0.4
|
||||||
@@ -2377,6 +2432,8 @@ snapshots:
|
|||||||
|
|
||||||
longest-streak@3.1.0: {}
|
longest-streak@3.1.0: {}
|
||||||
|
|
||||||
|
loupe@3.1.3: {}
|
||||||
|
|
||||||
map-age-cleaner@0.1.3:
|
map-age-cleaner@0.1.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
p-defer: 1.0.0
|
p-defer: 1.0.0
|
||||||
@@ -2859,6 +2916,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
unique-string: 2.0.0
|
unique-string: 2.0.0
|
||||||
|
|
||||||
|
pathval@2.0.0: {}
|
||||||
|
|
||||||
picocolors@1.1.1: {}
|
picocolors@1.1.1: {}
|
||||||
|
|
||||||
picomatch@2.3.1: {}
|
picomatch@2.3.1: {}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const codeHandler: ExecutionHandler = ({
|
|||||||
node,
|
node,
|
||||||
addStep,
|
addStep,
|
||||||
}) => {
|
}) => {
|
||||||
if (node.type !== 'code' || node.lang === 'http') {
|
if (node.type !== 'code' || node.lang === 'http' || node.lang === 'javascript') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const optionParts = node.meta?.split(',') || [];
|
const optionParts = node.meta?.split(',') || [];
|
||||||
|
|||||||
73
src/execution/handlers/handlers.javascript.ts
Normal file
73
src/execution/handlers/handlers.javascript.ts
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import Handlebars from "handlebars";
|
||||||
|
import YAML from "yaml";
|
||||||
|
import { should, expect, assert } from 'chai';
|
||||||
|
import { ExecutionHandler } from "../execution.js";
|
||||||
|
|
||||||
|
const javascriptHandler: ExecutionHandler = ({
|
||||||
|
node,
|
||||||
|
parent,
|
||||||
|
index,
|
||||||
|
addStep,
|
||||||
|
}) => {
|
||||||
|
if (node.type !== 'code' || node.lang !== 'javascript') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const optionParts = node.meta?.split(',') || [];
|
||||||
|
node.meta = undefined;
|
||||||
|
const options = Object.fromEntries(
|
||||||
|
optionParts.filter(Boolean).map((option) => {
|
||||||
|
const [key, value] = option.split('=');
|
||||||
|
return [key.trim(), value?.trim() || true];
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
addStep({
|
||||||
|
type: 'code',
|
||||||
|
node,
|
||||||
|
action: async ({ context }) => {
|
||||||
|
const template = Handlebars.compile(node.value);
|
||||||
|
const content = template(context);
|
||||||
|
node.value = content;
|
||||||
|
if (options['run'] === true) {
|
||||||
|
const api = {
|
||||||
|
assert,
|
||||||
|
should,
|
||||||
|
expect,
|
||||||
|
...context,
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line no-new-func
|
||||||
|
const asyncFunc = new Function(
|
||||||
|
...Object.keys(api),
|
||||||
|
`return (async () => { ${content} })()`
|
||||||
|
);
|
||||||
|
const result = await asyncFunc(...Object.values(api));
|
||||||
|
if (options.output === true && index !== undefined) {
|
||||||
|
if (result !== undefined) {
|
||||||
|
parent?.children?.splice(index + 1, 0, {
|
||||||
|
type: 'code',
|
||||||
|
lang: 'yaml',
|
||||||
|
value: YAML.stringify(result, null, 2),
|
||||||
|
meta: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (index !== undefined) {
|
||||||
|
parent?.children?.splice(index + 1, 0, {
|
||||||
|
type: 'code',
|
||||||
|
value: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
||||||
|
meta: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (options.hidden === true && parent && index !== undefined) {
|
||||||
|
parent.children?.splice(index, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export { javascriptHandler };
|
||||||
@@ -7,6 +7,7 @@ import { responseHandler } from "./handlers.response.js";
|
|||||||
import { textHandler } from "./handlers.text.js";
|
import { textHandler } from "./handlers.text.js";
|
||||||
import { codeHandler } from "./handlers.code.js";
|
import { codeHandler } from "./handlers.code.js";
|
||||||
import { tocHandler } from "./handlers.toc.js";
|
import { tocHandler } from "./handlers.toc.js";
|
||||||
|
import { javascriptHandler } from "./handlers.javascript.js";
|
||||||
|
|
||||||
const handlers = [
|
const handlers = [
|
||||||
fileHandler,
|
fileHandler,
|
||||||
@@ -16,6 +17,7 @@ const handlers = [
|
|||||||
inputHandler,
|
inputHandler,
|
||||||
rawMdHandler,
|
rawMdHandler,
|
||||||
codeHandler,
|
codeHandler,
|
||||||
|
javascriptHandler,
|
||||||
] satisfies ExecutionHandler[];
|
] satisfies ExecutionHandler[];
|
||||||
|
|
||||||
const postHandlers = [
|
const postHandlers = [
|
||||||
|
|||||||
Reference in New Issue
Block a user