mirror of
https://github.com/morten-olsen/http.md.git
synced 2026-02-08 00:46:28 +01:00
feat: support template in all code blocks
This commit is contained in:
29
README.md
29
README.md
@@ -112,7 +112,7 @@ access-control-allow-origin: *
|
|||||||
connection: keep-alive
|
connection: keep-alive
|
||||||
content-length: 559
|
content-length: 559
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
date: Sun, 18 May 2025 17:17:15 GMT
|
date: Sun, 18 May 2025 18:31:46 GMT
|
||||||
server: gunicorn/19.9.0
|
server: gunicorn/19.9.0
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -129,7 +129,7 @@ server: gunicorn/19.9.0
|
|||||||
"Host": "httpbin.org",
|
"Host": "httpbin.org",
|
||||||
"Sec-Fetch-Mode": "cors",
|
"Sec-Fetch-Mode": "cors",
|
||||||
"User-Agent": "node",
|
"User-Agent": "node",
|
||||||
"X-Amzn-Trace-Id": "Root=1-682a161b-6f8d778138665a8f22ffbe94"
|
"X-Amzn-Trace-Id": "Root=1-682a2792-7df702ce77a3b3696937eaeb"
|
||||||
},
|
},
|
||||||
"json": {
|
"json": {
|
||||||
"greeting": "Hello, http.md!"
|
"greeting": "Hello, http.md!"
|
||||||
@@ -292,7 +292,7 @@ GET https://httpbin.org/anything/{{responses.createItem.body.json.name}}
|
|||||||
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: ****.
|
||||||
````
|
````
|
||||||
|
|
||||||
## Managing Documents
|
## Managing Documents
|
||||||
@@ -324,7 +324,7 @@ Let's include some shared requests:
|
|||||||
|
|
||||||
::md[./_shared_requests.md]
|
::md[./_shared_requests.md]
|
||||||
|
|
||||||
The shared GET request returned: {{responses.sharedGetRequest.status}}
|
The shared GET request returned:
|
||||||
|
|
||||||
Now, a request specific to this document:
|
Now, a request specific to this document:
|
||||||
|
|
||||||
@@ -332,7 +332,7 @@ Now, a request specific to this document:
|
|||||||
POST https://httpbin.org/post
|
POST https://httpbin.org/post
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{"dataFromMain": "someValue", "sharedUrl": "{{requests.sharedGetRequest.url}}"}
|
{"dataFromMain": "someValue", "sharedUrl": ""}
|
||||||
```
|
```
|
||||||
|
|
||||||
::response
|
::response
|
||||||
@@ -356,8 +356,8 @@ httpmd build mydoc.md output.md -i baseUrl=https://api.production.example.com -i
|
|||||||
|
|
||||||
````markdown
|
````markdown
|
||||||
```http
|
```http
|
||||||
GET {{input.baseUrl}}/users/1
|
GET /users/1
|
||||||
Authorization: Bearer {{input.apiKey}}
|
Authorization: Bearer
|
||||||
```
|
```
|
||||||
|
|
||||||
::response
|
::response
|
||||||
@@ -406,8 +406,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 /data
|
||||||
X-API-Key: {{input.apiKey}}
|
X-API-Key:
|
||||||
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
|
||||||
@@ -445,6 +445,17 @@ The `::md` directive embeds another markdown document.
|
|||||||
* `hidden`: If present, the actual content (markdown) of the embedded document will not be rendered in the output. However, any `http` requests within the embedded document *are still processed*, and their `request` and `response` data become available in the parent document's templating context (via `requests.id` and `responses.id`). This is useful if you only want to execute the requests from an included file (e.g., a common setup sequence) and use their results, without displaying the embedded file's content.
|
* `hidden`: If present, the actual content (markdown) of the embedded document will not be rendered in the output. However, any `http` requests within the embedded document *are still processed*, and their `request` and `response` data become available in the parent document's templating context (via `requests.id` and `responses.id`). This is useful if you only want to execute the requests from an included file (e.g., a common setup sequence) and use their results, without displaying the embedded file's content.
|
||||||
* Example: `::md[./setup_requests.md]{hidden}`
|
* Example: `::md[./setup_requests.md]{hidden}`
|
||||||
|
|
||||||
|
#### `::input[{name}]` Directive Options
|
||||||
|
|
||||||
|
The `::input` directive is used to declare expected input variables
|
||||||
|
|
||||||
|
* **Variable Name:** The first argument (required) is the name of the variable
|
||||||
|
* Example: `::input[myVariable]` will define `input.myVariable`
|
||||||
|
* `required`: If present it will require that the variable is provided
|
||||||
|
* `default={value}`: Defines the default value if no value has been provided
|
||||||
|
* `format=string|number|bool|json|date`: If provided the value will be parsed using the specified format
|
||||||
|
* \`\`
|
||||||
|
|
||||||
## Command-Line Interface (CLI)
|
## Command-Line Interface (CLI)
|
||||||
|
|
||||||
The `httpmd` tool provides the following commands:
|
The `httpmd` tool provides the following commands:
|
||||||
|
|||||||
34
src/execution/handlers/handlers.code.ts
Normal file
34
src/execution/handlers/handlers.code.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import Handlebars from "handlebars";
|
||||||
|
import { ExecutionHandler } from "../execution.js";
|
||||||
|
|
||||||
|
const codeHandler: ExecutionHandler = ({
|
||||||
|
node,
|
||||||
|
addStep,
|
||||||
|
}) => {
|
||||||
|
if (node.type !== 'code' || node.lang === 'http') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const optionParts = node.meta?.split(',') || [];
|
||||||
|
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 }) => {
|
||||||
|
node.meta = undefined;
|
||||||
|
if (options['no-tmpl'] === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const template = Handlebars.compile(node.value);
|
||||||
|
const content = template(context);
|
||||||
|
node.value = content;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export { codeHandler };
|
||||||
@@ -6,8 +6,7 @@ const httpHandler: ExecutionHandler = ({
|
|||||||
node,
|
node,
|
||||||
addStep,
|
addStep,
|
||||||
}) => {
|
}) => {
|
||||||
if (node.type === 'code') {
|
if (node.type !== 'code' || node.lang !== 'http') {
|
||||||
if (node.lang !== 'http') {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const optionParts = node.meta?.split(',') || [];
|
const optionParts = node.meta?.split(',') || [];
|
||||||
@@ -83,8 +82,6 @@ const httpHandler: ExecutionHandler = ({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export { httpHandler };
|
export { httpHandler };
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { ExecutionHandler } from "../execution.js";
|
import { ExecutionHandler } from "../execution.js";
|
||||||
import { fileHandler } from "./handlers.file.js";
|
import { fileHandler } from "./handlers.md.js";
|
||||||
import { httpHandler } from "./handlers.http.js";
|
import { httpHandler } from "./handlers.http.js";
|
||||||
import { inputHandler } from "./handlers.input.js";
|
import { inputHandler } from "./handlers.input.js";
|
||||||
import { rawMdHandler } from "./handlers.raw-md.js";
|
import { rawMdHandler } from "./handlers.raw-md.js";
|
||||||
import { responseHandler } from "./handlers.response.js";
|
import { responseHandler } from "./handlers.response.js";
|
||||||
import { textHandler } from "./handlers.text.js";
|
import { textHandler } from "./handlers.text.js";
|
||||||
|
import { codeHandler } from "./handlers.code.js";
|
||||||
|
|
||||||
const handlers = [
|
const handlers = [
|
||||||
fileHandler,
|
fileHandler,
|
||||||
@@ -13,6 +14,7 @@ const handlers = [
|
|||||||
textHandler,
|
textHandler,
|
||||||
inputHandler,
|
inputHandler,
|
||||||
rawMdHandler,
|
rawMdHandler,
|
||||||
|
codeHandler,
|
||||||
] satisfies ExecutionHandler[];
|
] satisfies ExecutionHandler[];
|
||||||
|
|
||||||
export { handlers };
|
export { handlers };
|
||||||
|
|||||||
Reference in New Issue
Block a user