mirror of
https://github.com/morten-olsen/http.md.git
synced 2026-02-08 00:46:28 +01:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e79f9e958 |
11
.github/workflows/main.yaml
vendored
11
.github/workflows/main.yaml
vendored
@@ -20,7 +20,7 @@ env:
|
|||||||
IMAGE_NAME: ${{ github.repository }}
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: write
|
||||||
packages: read
|
packages: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -92,7 +92,7 @@ jobs:
|
|||||||
|
|
||||||
release:
|
release:
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
attestations: write
|
attestations: write
|
||||||
id-token: write
|
id-token: write
|
||||||
@@ -132,11 +132,6 @@ jobs:
|
|||||||
git config user.name "Github Actions Bot"
|
git config user.name "Github Actions Bot"
|
||||||
git config user.email "<>"
|
git config user.email "<>"
|
||||||
node ./scripts/set-version.mjs $(git describe --tag --abbrev=0)
|
node ./scripts/set-version.mjs $(git describe --tag --abbrev=0)
|
||||||
pnpm publish --no-git-checks --access public
|
pnpm publish --access public
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|
||||||
- uses: stefanzweifel/git-auto-commit-action@v5
|
|
||||||
with:
|
|
||||||
commit_message: "docs: generated README"
|
|
||||||
file_pattern: "*.md"
|
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,2 @@
|
|||||||
/node_modules/
|
/node_modules/
|
||||||
/dist/
|
/dist/
|
||||||
/*.html
|
|
||||||
|
|||||||
91
README.md
91
README.md
@@ -26,11 +26,9 @@ It allows developers to create API documentation that is always accurate and up-
|
|||||||
Install `http.md` globally using npm:
|
Install `http.md` globally using npm:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
npm i -g http.md
|
npm i -g @morten-olsen/httpmd
|
||||||
```
|
```
|
||||||
|
|
||||||
Or use `npx http.md` instead of `http.md`
|
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
### Your First Request
|
### Your First Request
|
||||||
@@ -64,13 +62,13 @@ You have two primary ways to render your `http.md` file:
|
|||||||
For a development server that outputs to your terminal and watches for changes:
|
For a development server that outputs to your terminal and watches for changes:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
http.md dev example.md
|
httpmd dev example.md
|
||||||
```
|
```
|
||||||
|
|
||||||
With watch mode:
|
With watch mode:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
http.md dev --watch example.md
|
httpmd dev --watch example.md
|
||||||
```
|
```
|
||||||
|
|
||||||
This command will process `example.md`, execute the HTTP requests, and print the resulting markdown (with responses filled in) to the terminal. With `--watch`, any changes to `example.md` will trigger a re-run.
|
This command will process `example.md`, execute the HTTP requests, and print the resulting markdown (with responses filled in) to the terminal. With `--watch`, any changes to `example.md` will trigger a re-run.
|
||||||
@@ -79,13 +77,13 @@ You have two primary ways to render your `http.md` file:
|
|||||||
To generate a new markdown file with the responses and templated values rendered:
|
To generate a new markdown file with the responses and templated values rendered:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
http.md build example.md output.md
|
httpmd build example.md output.md
|
||||||
```
|
```
|
||||||
|
|
||||||
With watch mode:
|
With watch mode:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
http.md build --watch example.md output.md
|
httpmd build --watch example.md output.md
|
||||||
```
|
```
|
||||||
|
|
||||||
This creates `output.md`, which is a static snapshot of `example.md` after all requests have been executed and templating applied. This file is suitable for version control, sharing, or integration with static site generators.
|
This creates `output.md`, which is a static snapshot of `example.md` after all requests have been executed and templating applied. This file is suitable for version control, sharing, or integration with static site generators.
|
||||||
@@ -111,9 +109,9 @@ HTTP/200 OK
|
|||||||
access-control-allow-credentials: true
|
access-control-allow-credentials: true
|
||||||
access-control-allow-origin: *
|
access-control-allow-origin: *
|
||||||
connection: keep-alive
|
connection: keep-alive
|
||||||
content-length: 555
|
content-length: 559
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
date: Sun, 18 May 2025 19:12:17 GMT
|
date: Sun, 18 May 2025 18:31:46 GMT
|
||||||
server: gunicorn/19.9.0
|
server: gunicorn/19.9.0
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -130,12 +128,11 @@ 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-682a3111-131bcbff690b03fd64aa4617"
|
"X-Amzn-Trace-Id": "Root=1-682a2792-7df702ce77a3b3696937eaeb"
|
||||||
},
|
},
|
||||||
"json": {
|
"json": {
|
||||||
"greeting": "Hello, http.md!"
|
"greeting": "Hello, http.md!"
|
||||||
},
|
},
|
||||||
"origin": "23.96.180.7",
|
|
||||||
"url": "https://httpbin.org/post"
|
"url": "https://httpbin.org/post"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,21 +253,21 @@ Within your markdown document, the following variables are available in the Hand
|
|||||||
|
|
||||||
- **`input`** (Object): A dictionary of variables passed to `http.md` via the command line using the `-i` or `--input` flag.
|
- **`input`** (Object): A dictionary of variables passed to `http.md` via the command line using the `-i` or `--input` flag.
|
||||||
|
|
||||||
- Example: If you run `http.md dev -i userId=123 -i apiKey=secret myfile.md`, you can use `{{input.userId}}` and `{{input.apiKey}}`.
|
- Example: If you run `httpmd dev -i userId=123 -i apiKey=secret myfile.md`, you can use `{{input.userId}}` and `{{input.apiKey}}`.
|
||||||
|
|
||||||
### Templating Examples
|
### Templating Examples
|
||||||
|
|
||||||
**1. Using a value from a previous response in a new request:**
|
**1. Using a value from a previous response in a new request:**
|
||||||
|
|
||||||
````markdown
|
````markdown
|
||||||
```http #createItem,json
|
```http id=createItem json
|
||||||
POST https://httpbin.org/post
|
POST https://httpbin.org/post
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{"name": "My New Item"}
|
{"name": "My New Item"}
|
||||||
```
|
```
|
||||||
|
|
||||||
The new item ID is: {{response.body.json.name}}
|
The new item ID is: {{responses.createItem.body.json.name}}
|
||||||
|
|
||||||
Now, let's fetch the item using a (mocked) ID from the response:
|
Now, let's fetch the item using a (mocked) ID from the response:
|
||||||
|
|
||||||
@@ -281,60 +278,6 @@ GET https://httpbin.org/anything/{{responses.createItem.body.json.name}}
|
|||||||
::response{#fetchItem}
|
::response{#fetchItem}
|
||||||
````
|
````
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Output</summary>
|
|
||||||
|
|
||||||
````markdown
|
|
||||||
```http
|
|
||||||
POST https://httpbin.org/post
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{"name": "My New Item"}
|
|
||||||
```
|
|
||||||
|
|
||||||
The new item ID is: My New Item
|
|
||||||
|
|
||||||
Now, let's fetch the item using a (mocked) ID from the response:
|
|
||||||
|
|
||||||
```http
|
|
||||||
GET https://httpbin.org/anything/My New Item
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
HTTP/200 OK
|
|
||||||
access-control-allow-credentials: true
|
|
||||||
access-control-allow-origin: *
|
|
||||||
connection: keep-alive
|
|
||||||
content-length: 451
|
|
||||||
content-type: application/json
|
|
||||||
date: Sun, 18 May 2025 19:12:18 GMT
|
|
||||||
server: gunicorn/19.9.0
|
|
||||||
|
|
||||||
{
|
|
||||||
"args": {},
|
|
||||||
"data": "",
|
|
||||||
"files": {},
|
|
||||||
"form": {},
|
|
||||||
"headers": {
|
|
||||||
"Accept": "*/*",
|
|
||||||
"Accept-Encoding": "br, gzip, deflate",
|
|
||||||
"Accept-Language": "*",
|
|
||||||
"Host": "httpbin.org",
|
|
||||||
"Sec-Fetch-Mode": "cors",
|
|
||||||
"User-Agent": "node",
|
|
||||||
"X-Amzn-Trace-Id": "Root=1-682a3112-4bbb29111129c1556c487ca1"
|
|
||||||
},
|
|
||||||
"json": null,
|
|
||||||
"method": "GET",
|
|
||||||
"origin": "23.96.180.7",
|
|
||||||
"url": "https://httpbin.org/anything/My New Item"
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
````
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
_(Note: `httpbin.org/post` wraps the JSON sent in a "json" field in its response. If your API returns the ID directly at the root of the JSON body, you'd use `{{responses.createItem.body.id}}` assuming the `createItem` request had the `json` option.)_
|
_(Note: `httpbin.org/post` wraps the JSON sent in a "json" field in its response. If your API returns the ID directly at the root of the JSON body, you'd use `{{responses.createItem.body.id}}` assuming the `createItem` request had the `json` option.)_
|
||||||
|
|
||||||
**2. Displaying a status code in markdown text:**
|
**2. Displaying a status code in markdown text:**
|
||||||
@@ -401,7 +344,7 @@ You can pass external data into your `http.md` documents using the `-i` (or `--i
|
|||||||
**CLI Command:**
|
**CLI Command:**
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
http.md build mydoc.md output.md -i baseUrl=https://api.production.example.com -i apiKey=YOUR_SECRET_KEY
|
httpmd build mydoc.md output.md -i baseUrl=https://api.production.example.com -i apiKey=YOUR_SECRET_KEY
|
||||||
```
|
```
|
||||||
|
|
||||||
**Markdown Usage (`mydoc.md`):**
|
**Markdown Usage (`mydoc.md`):**
|
||||||
@@ -510,9 +453,9 @@ The `::input` directive is used to declare expected input variables
|
|||||||
|
|
||||||
## Command-Line Interface (CLI)
|
## Command-Line Interface (CLI)
|
||||||
|
|
||||||
The `http.md` tool provides the following commands:
|
The `httpmd` tool provides the following commands:
|
||||||
|
|
||||||
### `http.md dev <source_file.md>`
|
### `httpmd dev <source_file.md>`
|
||||||
|
|
||||||
Processes the `<source_file.md>`, executes all HTTP requests, resolves templates, and prints the resulting markdown to the **terminal (stdout)**.
|
Processes the `<source_file.md>`, executes all HTTP requests, resolves templates, and prints the resulting markdown to the **terminal (stdout)**.
|
||||||
|
|
||||||
@@ -524,10 +467,10 @@ Processes the `<source_file.md>`, executes all HTTP requests, resolves templates
|
|||||||
**Example:**
|
**Example:**
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
http.md dev api_tests.md --watch -i host=localhost:3000
|
httpmd dev api_tests.md --watch -i host=localhost:3000
|
||||||
```
|
```
|
||||||
|
|
||||||
### `http.md build <source_file.md> <output_file.md>`
|
### `httpmd build <source_file.md> <output_file.md>`
|
||||||
|
|
||||||
Processes the `<source_file.md>`, executes all HTTP requests, resolves templates, and saves the resulting markdown to `<output_file.md>`.
|
Processes the `<source_file.md>`, executes all HTTP requests, resolves templates, and saves the resulting markdown to `<output_file.md>`.
|
||||||
|
|
||||||
@@ -539,5 +482,5 @@ Processes the `<source_file.md>`, executes all HTTP requests, resolves templates
|
|||||||
**Example:**
|
**Example:**
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
http.md build official_api_docs.md public/api_docs_v1.md -i version=v1.0
|
httpmd build official_api_docs.md public/api_docs_v1.md -i version=v1.0
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -21,10 +21,6 @@ It allows developers to create API documentation that is always accurate and up-
|
|||||||
- **Tutorials & Guides:** Build step-by-step guides where each HTTP interaction is shown with its real output.
|
- **Tutorials & Guides:** Build step-by-step guides where each HTTP interaction is shown with its real output.
|
||||||
- **Rapid Prototyping:** Quickly experiment with APIs and document your findings.
|
- **Rapid Prototyping:** Quickly experiment with APIs and document your findings.
|
||||||
|
|
||||||
## Content
|
|
||||||
|
|
||||||
::toc
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Install `http.md` globally using npm:
|
Install `http.md` globally using npm:
|
||||||
@@ -132,17 +128,10 @@ You can assign a unique ID to an `http` request block. This allows you to:
|
|||||||
1. Reference its specific response in a `::response` directive.
|
1. Reference its specific response in a `::response` directive.
|
||||||
2. Access its request and response data in [Templating](https://www.google.com/search?q=%23templating-with-handlebars) via the `requests` and `responses` dictionaries.
|
2. Access its request and response data in [Templating](https://www.google.com/search?q=%23templating-with-handlebars) via the `requests` and `responses` dictionaries.
|
||||||
|
|
||||||
To add an ID, include `#yourUniqueId` or `id=yourUniqueId` in the `http` block's info string:
|
To add an ID, include `id=yourUniqueId` in the `http` block's info string:
|
||||||
|
|
||||||
::raw-md[./examples/with-multiple-requests.md]
|
::raw-md[./examples/with-multiple-requests.md]
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Output</summary>
|
|
||||||
|
|
||||||
::raw-md[./examples/with-multiple-requests.md]{render}
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Templating with Handlebars
|
## Templating with Handlebars
|
||||||
|
|
||||||
`http.md` uses [Handlebars](https://handlebarsjs.com/) for templating, allowing you to create dynamic content within your markdown files. You can inject data from request responses, input variables, and other requests into your HTTP blocks or general markdown text.
|
`http.md` uses [Handlebars](https://handlebarsjs.com/) for templating, allowing you to create dynamic content within your markdown files. You can inject data from request responses, input variables, and other requests into your HTTP blocks or general markdown text.
|
||||||
@@ -187,13 +176,6 @@ Within your markdown document, the following variables are available in the Hand
|
|||||||
|
|
||||||
::raw-md[./examples/with-template.md]
|
::raw-md[./examples/with-template.md]
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Output</summary>
|
|
||||||
|
|
||||||
::raw-md[./examples/with-template.md]{render}
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
_(Note: `httpbin.org/post` wraps the JSON sent in a "json" field in its response. If your API returns the ID directly at the root of the JSON body, you'd use `{{responses.createItem.body.id}}` assuming the `createItem` request had the `json` option.)_
|
_(Note: `httpbin.org/post` wraps the JSON sent in a "json" field in its response. If your API returns the ID directly at the root of the JSON body, you'd use `{{responses.createItem.body.id}}` assuming the `createItem` request had the `json` option.)_
|
||||||
|
|
||||||
**2. Displaying a status code in markdown text:**
|
**2. Displaying a status code in markdown text:**
|
||||||
@@ -220,18 +202,34 @@ The requests from the embedded document are processed, and their `request` and `
|
|||||||
|
|
||||||
Assume `_shared_requests.md` contains:
|
Assume `_shared_requests.md` contains:
|
||||||
|
|
||||||
::raw-md[./examples/_shared_requests.md]
|
````markdown
|
||||||
|
```http id=sharedGetRequest
|
||||||
|
GET https://httpbin.org/get
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
Then, in `main.md`:
|
Then, in `main.md`:
|
||||||
|
|
||||||
::raw-md[./examples/with-shared-requests.md]
|
````markdown
|
||||||
|
# Main Document
|
||||||
|
|
||||||
<details>
|
Let's include some shared requests:
|
||||||
<summary>Output</summary>
|
|
||||||
|
|
||||||
::raw-md[./examples/with-shared-requests.md]{render}
|
::md[./_shared_requests.md]
|
||||||
|
|
||||||
</details>
|
The shared GET request returned: {{responses.sharedGetRequest.status}}
|
||||||
|
|
||||||
|
Now, a request specific to this document:
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST https://httpbin.org/post
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{"dataFromMain": "someValue", "sharedUrl": "{{requests.sharedGetRequest.url}}"}
|
||||||
|
```
|
||||||
|
|
||||||
|
::response
|
||||||
|
````
|
||||||
|
|
||||||
When `main.md` is processed, `_shared_requests.md` will be embedded, its `sharedGetRequest` will be executed, and its data will be available for templating.
|
When `main.md` is processed, `_shared_requests.md` will be embedded, its `sharedGetRequest` will be executed, and its data will be available for templating.
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
```http #sharedGetRequest
|
|
||||||
GET https://httpbin.org/get
|
|
||||||
```
|
|
||||||
@@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
First, create a resource:
|
First, create a resource:
|
||||||
|
|
||||||
```http #createUser,yaml,json
|
```http id=createUser
|
||||||
POST https://httpbin.org/post
|
POST https://httpbin.org/post
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
username: alpha
|
{"username": "alpha"}
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, fetch a different resource:
|
Then, fetch a different resource:
|
||||||
|
|
||||||
```http #getItem
|
```http id=getItem
|
||||||
GET https://httpbin.org/get?item=123
|
GET https://httpbin.org/get?item=123
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
# Main Document
|
|
||||||
|
|
||||||
Let's include some shared requests:
|
|
||||||
|
|
||||||
::md[./_shared_requests.md]
|
|
||||||
|
|
||||||
The shared GET request returned: {{response.statusText}}
|
|
||||||
|
|
||||||
Now, a request specific to this document:
|
|
||||||
|
|
||||||
```http
|
|
||||||
POST https://httpbin.org/post
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{"dataFromMain": "someValue", "sharedUrl": "{{requests.sharedGetRequest.url}}"}
|
|
||||||
```
|
|
||||||
|
|
||||||
::response
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
```http #createItem,json
|
```http id=createItem json
|
||||||
POST https://httpbin.org/post
|
POST https://httpbin.org/post
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{"name": "My New Item"}
|
{"name": "My New Item"}
|
||||||
```
|
```
|
||||||
|
|
||||||
The new item ID is: {{response.body.json.name}}
|
The new item ID is: {{responses.createItem.body.json.name}}
|
||||||
|
|
||||||
Now, let's fetch the item using a (mocked) ID from the response:
|
Now, let's fetch the item using a (mocked) ID from the response:
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "http.md",
|
"name": "@morten-olsen/httpmd",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "dist/exports.js",
|
"main": "dist/exports.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bin": {
|
"bin": {
|
||||||
"http.md": "./bin/cli.mjs"
|
"httpmd": "./bin/cli.mjs"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
"build": "pnpm run build:lib && pnpm run build:readme",
|
"build": "pnpm run build:lib && pnpm run build:readme",
|
||||||
"build:lib": "tsc --build",
|
"build:lib": "tsc --build",
|
||||||
"build:readme": "pnpm run cli build docs/README.md README.md",
|
"build:readme": "pnpm run cli build docs/README.md README.md",
|
||||||
"build:readme-html": "pnpm run cli build docs/README.md README.html -f html",
|
|
||||||
"dev:readme": "pnpm run cli dev docs/README.md --watch",
|
"dev:readme": "pnpm run cli dev docs/README.md --watch",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
@@ -36,7 +35,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"blessed": "^0.1.81",
|
"blessed": "^0.1.81",
|
||||||
"chalk": "^5.4.1",
|
|
||||||
"commander": "^14.0.0",
|
"commander": "^14.0.0",
|
||||||
"dotenv": "^16.5.0",
|
"dotenv": "^16.5.0",
|
||||||
"eventemitter3": "^5.0.1",
|
"eventemitter3": "^5.0.1",
|
||||||
@@ -46,9 +44,7 @@
|
|||||||
"marked-terminal": "^7.3.0",
|
"marked-terminal": "^7.3.0",
|
||||||
"mdast-util-to-markdown": "^2.1.2",
|
"mdast-util-to-markdown": "^2.1.2",
|
||||||
"mdast-util-to-string": "^4.0.0",
|
"mdast-util-to-string": "^4.0.0",
|
||||||
"mdast-util-toc": "^7.1.0",
|
|
||||||
"rehype-stringify": "^10.0.1",
|
"rehype-stringify": "^10.0.1",
|
||||||
"remark-behead": "^3.1.0",
|
|
||||||
"remark-directive": "^4.0.0",
|
"remark-directive": "^4.0.0",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"remark-parse": "^11.0.0",
|
"remark-parse": "^11.0.0",
|
||||||
|
|||||||
128
pnpm-lock.yaml
generated
128
pnpm-lock.yaml
generated
@@ -11,9 +11,6 @@ importers:
|
|||||||
blessed:
|
blessed:
|
||||||
specifier: ^0.1.81
|
specifier: ^0.1.81
|
||||||
version: 0.1.81
|
version: 0.1.81
|
||||||
chalk:
|
|
||||||
specifier: ^5.4.1
|
|
||||||
version: 5.4.1
|
|
||||||
commander:
|
commander:
|
||||||
specifier: ^14.0.0
|
specifier: ^14.0.0
|
||||||
version: 14.0.0
|
version: 14.0.0
|
||||||
@@ -41,15 +38,9 @@ importers:
|
|||||||
mdast-util-to-string:
|
mdast-util-to-string:
|
||||||
specifier: ^4.0.0
|
specifier: ^4.0.0
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
mdast-util-toc:
|
|
||||||
specifier: ^7.1.0
|
|
||||||
version: 7.1.0
|
|
||||||
rehype-stringify:
|
rehype-stringify:
|
||||||
specifier: ^10.0.1
|
specifier: ^10.0.1
|
||||||
version: 10.0.1
|
version: 10.0.1
|
||||||
remark-behead:
|
|
||||||
specifier: ^3.1.0
|
|
||||||
version: 3.1.0
|
|
||||||
remark-directive:
|
remark-directive:
|
||||||
specifier: ^4.0.0
|
specifier: ^4.0.0
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
@@ -464,9 +455,6 @@ packages:
|
|||||||
'@types/terminal-kit@2.5.7':
|
'@types/terminal-kit@2.5.7':
|
||||||
resolution: {integrity: sha512-IpbCBFSb3OqCEZBZlk368tGftqss88eNQaJdD9msEShRbksEiVahEqroONi60ppUt9/arLM6IDrHMx9jpzzCOw==}
|
resolution: {integrity: sha512-IpbCBFSb3OqCEZBZlk368tGftqss88eNQaJdD9msEShRbksEiVahEqroONi60ppUt9/arLM6IDrHMx9jpzzCOw==}
|
||||||
|
|
||||||
'@types/ungap__structured-clone@1.2.0':
|
|
||||||
resolution: {integrity: sha512-ZoaihZNLeZSxESbk9PUAPZOlSpcKx81I1+4emtULDVmBLkYutTcMlCj2K9VNlf9EWODxdO6gkAqEaLorXwZQVA==}
|
|
||||||
|
|
||||||
'@types/unist@2.0.11':
|
'@types/unist@2.0.11':
|
||||||
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
|
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
|
||||||
|
|
||||||
@@ -752,9 +740,6 @@ packages:
|
|||||||
get-tsconfig@4.10.0:
|
get-tsconfig@4.10.0:
|
||||||
resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==}
|
resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==}
|
||||||
|
|
||||||
github-slugger@2.0.0:
|
|
||||||
resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==}
|
|
||||||
|
|
||||||
glob-parent@5.1.2:
|
glob-parent@5.1.2:
|
||||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
@@ -905,9 +890,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==}
|
resolution: {integrity: sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
lodash.iteratee@4.7.0:
|
|
||||||
resolution: {integrity: sha512-yv3cSQZmfpbIKo4Yo45B1taEvxjNvcpF1CEOc0Y6dEyvhPIfEJE3twDwPgWTPQubcSgXyBwBKG6wpQvWMDOf6Q==}
|
|
||||||
|
|
||||||
longest-streak@3.1.0:
|
longest-streak@3.1.0:
|
||||||
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
|
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
|
||||||
|
|
||||||
@@ -977,9 +959,6 @@ packages:
|
|||||||
mdast-util-to-string@4.0.0:
|
mdast-util-to-string@4.0.0:
|
||||||
resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
|
resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
|
||||||
|
|
||||||
mdast-util-toc@7.1.0:
|
|
||||||
resolution: {integrity: sha512-2TVKotOQzqdY7THOdn2gGzS9d1Sdd66bvxUyw3aNpWfcPXCLYSJCCgfPy30sEtuzkDraJgqF35dzgmz6xlvH/w==}
|
|
||||||
|
|
||||||
mem@8.1.1:
|
mem@8.1.1:
|
||||||
resolution: {integrity: sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==}
|
resolution: {integrity: sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -1248,10 +1227,6 @@ packages:
|
|||||||
rehype-stringify@10.0.1:
|
rehype-stringify@10.0.1:
|
||||||
resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==}
|
resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==}
|
||||||
|
|
||||||
remark-behead@3.1.0:
|
|
||||||
resolution: {integrity: sha512-rKns7st91lgppaD5YaH58O4ECFVXTVnkyYQBuCw4ISRE2TFK/iVySMaKbvV2pVbUVIjAaDciugrTI/tyuPOlWQ==}
|
|
||||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
|
||||||
|
|
||||||
remark-directive@4.0.0:
|
remark-directive@4.0.0:
|
||||||
resolution: {integrity: sha512-7sxn4RfF1o3izevPV1DheyGDD6X4c9hrGpfdUpm7uC++dqrnJxIZVkk7CoKqcLm0VUMAuOol7Mno3m6g8cfMuA==}
|
resolution: {integrity: sha512-7sxn4RfF1o3izevPV1DheyGDD6X4c9hrGpfdUpm7uC++dqrnJxIZVkk7CoKqcLm0VUMAuOol7Mno3m6g8cfMuA==}
|
||||||
|
|
||||||
@@ -1456,25 +1431,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==}
|
resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
unist-util-find-all-after@4.0.1:
|
|
||||||
resolution: {integrity: sha512-AO8++e6HJfwNoTrqkV7xSeW65e6uSsLRQST/9LWi8FmFSz1gS7TBd+DkL/CYiElsSZIQgT4J5U54v5/kJX5Nqg==}
|
|
||||||
|
|
||||||
unist-util-find-all-before@4.0.1:
|
|
||||||
resolution: {integrity: sha512-xg4UHtZ6VbcjQbfDtmLZch6kQYQFF3nfaW05Ie3+t2UectzeqSx/iqLmh/wWogwU+YDWnD40PjZKK7ORmCma+g==}
|
|
||||||
|
|
||||||
unist-util-find-all-between@2.1.0:
|
|
||||||
resolution: {integrity: sha512-OCCUtDD8UHKeODw3TPXyFDxPCbpgBzbGTTaDpR68nvxkwiVcawBqMVrokfBMvUi7ij2F5q7S4s4Jq5dvkcBt+w==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
|
|
||||||
unist-util-find@1.0.4:
|
|
||||||
resolution: {integrity: sha512-T5vI7IkhroDj7KxAIy057VbIeGnCXfso4d4GoUsjbAmDLQUkzAeszlBtzx1+KHgdsYYBygaqUBvrbYCfePedZw==}
|
|
||||||
|
|
||||||
unist-util-is@4.1.0:
|
|
||||||
resolution: {integrity: sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==}
|
|
||||||
|
|
||||||
unist-util-is@5.2.1:
|
|
||||||
resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==}
|
|
||||||
|
|
||||||
unist-util-is@6.0.0:
|
unist-util-is@6.0.0:
|
||||||
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
|
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
|
||||||
|
|
||||||
@@ -1484,21 +1440,9 @@ packages:
|
|||||||
unist-util-stringify-position@4.0.0:
|
unist-util-stringify-position@4.0.0:
|
||||||
resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
|
resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
|
||||||
|
|
||||||
unist-util-visit-parents@3.1.1:
|
|
||||||
resolution: {integrity: sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==}
|
|
||||||
|
|
||||||
unist-util-visit-parents@5.1.3:
|
|
||||||
resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==}
|
|
||||||
|
|
||||||
unist-util-visit-parents@6.0.1:
|
unist-util-visit-parents@6.0.1:
|
||||||
resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==}
|
resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==}
|
||||||
|
|
||||||
unist-util-visit@2.0.3:
|
|
||||||
resolution: {integrity: sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==}
|
|
||||||
|
|
||||||
unist-util-visit@4.1.2:
|
|
||||||
resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==}
|
|
||||||
|
|
||||||
unist-util-visit@5.0.0:
|
unist-util-visit@5.0.0:
|
||||||
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
|
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
|
||||||
|
|
||||||
@@ -1951,8 +1895,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/nextgen-events': 1.1.4
|
'@types/nextgen-events': 1.1.4
|
||||||
|
|
||||||
'@types/ungap__structured-clone@1.2.0': {}
|
|
||||||
|
|
||||||
'@types/unist@2.0.11': {}
|
'@types/unist@2.0.11': {}
|
||||||
|
|
||||||
'@types/unist@3.0.3': {}
|
'@types/unist@3.0.3': {}
|
||||||
@@ -2240,8 +2182,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
resolve-pkg-maps: 1.0.0
|
resolve-pkg-maps: 1.0.0
|
||||||
|
|
||||||
github-slugger@2.0.0: {}
|
|
||||||
|
|
||||||
glob-parent@5.1.2:
|
glob-parent@5.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
@@ -2373,8 +2313,6 @@ snapshots:
|
|||||||
strip-bom: 4.0.0
|
strip-bom: 4.0.0
|
||||||
type-fest: 0.6.0
|
type-fest: 0.6.0
|
||||||
|
|
||||||
lodash.iteratee@4.7.0: {}
|
|
||||||
|
|
||||||
longest-streak@3.1.0: {}
|
longest-streak@3.1.0: {}
|
||||||
|
|
||||||
map-age-cleaner@0.1.3:
|
map-age-cleaner@0.1.3:
|
||||||
@@ -2528,16 +2466,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/mdast': 4.0.4
|
'@types/mdast': 4.0.4
|
||||||
|
|
||||||
mdast-util-toc@7.1.0:
|
|
||||||
dependencies:
|
|
||||||
'@types/mdast': 4.0.4
|
|
||||||
'@types/ungap__structured-clone': 1.2.0
|
|
||||||
'@ungap/structured-clone': 1.3.0
|
|
||||||
github-slugger: 2.0.0
|
|
||||||
mdast-util-to-string: 4.0.0
|
|
||||||
unist-util-is: 6.0.0
|
|
||||||
unist-util-visit: 5.0.0
|
|
||||||
|
|
||||||
mem@8.1.1:
|
mem@8.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
map-age-cleaner: 0.1.3
|
map-age-cleaner: 0.1.3
|
||||||
@@ -2905,14 +2833,6 @@ snapshots:
|
|||||||
hast-util-to-html: 9.0.5
|
hast-util-to-html: 9.0.5
|
||||||
unified: 11.0.5
|
unified: 11.0.5
|
||||||
|
|
||||||
remark-behead@3.1.0:
|
|
||||||
dependencies:
|
|
||||||
unist-util-find: 1.0.4
|
|
||||||
unist-util-find-all-after: 4.0.1
|
|
||||||
unist-util-find-all-before: 4.0.1
|
|
||||||
unist-util-find-all-between: 2.1.0
|
|
||||||
unist-util-visit: 4.1.2
|
|
||||||
|
|
||||||
remark-directive@4.0.0:
|
remark-directive@4.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/mdast': 4.0.4
|
'@types/mdast': 4.0.4
|
||||||
@@ -3131,32 +3051,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
crypto-random-string: 2.0.0
|
crypto-random-string: 2.0.0
|
||||||
|
|
||||||
unist-util-find-all-after@4.0.1:
|
|
||||||
dependencies:
|
|
||||||
'@types/unist': 2.0.11
|
|
||||||
unist-util-is: 5.2.1
|
|
||||||
|
|
||||||
unist-util-find-all-before@4.0.1:
|
|
||||||
dependencies:
|
|
||||||
'@types/unist': 2.0.11
|
|
||||||
unist-util-is: 5.2.1
|
|
||||||
|
|
||||||
unist-util-find-all-between@2.1.0:
|
|
||||||
dependencies:
|
|
||||||
unist-util-find: 1.0.4
|
|
||||||
unist-util-is: 4.1.0
|
|
||||||
|
|
||||||
unist-util-find@1.0.4:
|
|
||||||
dependencies:
|
|
||||||
lodash.iteratee: 4.7.0
|
|
||||||
unist-util-visit: 2.0.3
|
|
||||||
|
|
||||||
unist-util-is@4.1.0: {}
|
|
||||||
|
|
||||||
unist-util-is@5.2.1:
|
|
||||||
dependencies:
|
|
||||||
'@types/unist': 2.0.11
|
|
||||||
|
|
||||||
unist-util-is@6.0.0:
|
unist-util-is@6.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 3.0.3
|
'@types/unist': 3.0.3
|
||||||
@@ -3169,33 +3063,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 3.0.3
|
'@types/unist': 3.0.3
|
||||||
|
|
||||||
unist-util-visit-parents@3.1.1:
|
|
||||||
dependencies:
|
|
||||||
'@types/unist': 2.0.11
|
|
||||||
unist-util-is: 4.1.0
|
|
||||||
|
|
||||||
unist-util-visit-parents@5.1.3:
|
|
||||||
dependencies:
|
|
||||||
'@types/unist': 2.0.11
|
|
||||||
unist-util-is: 5.2.1
|
|
||||||
|
|
||||||
unist-util-visit-parents@6.0.1:
|
unist-util-visit-parents@6.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 3.0.3
|
'@types/unist': 3.0.3
|
||||||
unist-util-is: 6.0.0
|
unist-util-is: 6.0.0
|
||||||
|
|
||||||
unist-util-visit@2.0.3:
|
|
||||||
dependencies:
|
|
||||||
'@types/unist': 2.0.11
|
|
||||||
unist-util-is: 4.1.0
|
|
||||||
unist-util-visit-parents: 3.1.1
|
|
||||||
|
|
||||||
unist-util-visit@4.1.2:
|
|
||||||
dependencies:
|
|
||||||
'@types/unist': 2.0.11
|
|
||||||
unist-util-is: 5.2.1
|
|
||||||
unist-util-visit-parents: 5.1.3
|
|
||||||
|
|
||||||
unist-util-visit@5.0.0:
|
unist-util-visit@5.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 3.0.3
|
'@types/unist': 3.0.3
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import { program } from 'commander';
|
import { program } from 'commander';
|
||||||
import { resolve } from 'node:path';
|
import { resolve } from 'node:path';
|
||||||
import { Marked } from 'marked';
|
import { marked } from 'marked';
|
||||||
import { markedTerminal } from 'marked-terminal';
|
import { markedTerminal } from 'marked-terminal';
|
||||||
import { execute } from '../execution/execution.js';
|
import { execute } from '../execution/execution.js';
|
||||||
import { Context } from '../context/context.js';
|
import { Context } from '../context/context.js';
|
||||||
import { writeFile } from 'node:fs/promises';
|
import { writeFile } from 'node:fs/promises';
|
||||||
import { Watcher } from '../watcher/watcher.js';
|
import { Watcher } from '../watcher/watcher.js';
|
||||||
import { UI } from './ui/ui.js';
|
|
||||||
import { wrapBody } from '../theme/theme.html.js';
|
|
||||||
|
|
||||||
|
|
||||||
|
marked.use(markedTerminal() as any);
|
||||||
|
|
||||||
program
|
program
|
||||||
.command('dev')
|
.command('dev')
|
||||||
@@ -18,15 +17,11 @@ program
|
|||||||
.option('-w, --watch', 'watch for changes')
|
.option('-w, --watch', 'watch for changes')
|
||||||
.option('-i, --input <input...>', 'input variables (-i foo=bar -i baz=qux)')
|
.option('-i, --input <input...>', 'input variables (-i foo=bar -i baz=qux)')
|
||||||
.action(async (name, options) => {
|
.action(async (name, options) => {
|
||||||
const marked = new Marked();
|
|
||||||
marked.use(markedTerminal() as any);
|
|
||||||
const {
|
const {
|
||||||
watch = false,
|
watch = false,
|
||||||
input: i = [],
|
input: i = [],
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const ui = new UI();
|
|
||||||
|
|
||||||
const input = Object.fromEntries(
|
const input = Object.fromEntries(
|
||||||
i.map((item: string) => {
|
i.map((item: string) => {
|
||||||
const [key, value] = item.split('=');
|
const [key, value] = item.split('=');
|
||||||
@@ -44,7 +39,7 @@ program
|
|||||||
});
|
});
|
||||||
|
|
||||||
const markdown = await marked.parse(result.markdown);
|
const markdown = await marked.parse(result.markdown);
|
||||||
ui.content = markdown;
|
console.log(markdown);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...result,
|
...result,
|
||||||
@@ -54,10 +49,6 @@ program
|
|||||||
|
|
||||||
const result = await build();
|
const result = await build();
|
||||||
|
|
||||||
ui.screen.key(['r'], () => {
|
|
||||||
build();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (watch) {
|
if (watch) {
|
||||||
const watcher = new Watcher();
|
const watcher = new Watcher();
|
||||||
watcher.watchFiles(Array.from(result.context.files));
|
watcher.watchFiles(Array.from(result.context.files));
|
||||||
@@ -75,14 +66,12 @@ program
|
|||||||
.argument('<name>', 'http.md file name')
|
.argument('<name>', 'http.md file name')
|
||||||
.argument('<output>', 'output file name')
|
.argument('<output>', 'output file name')
|
||||||
.description('Run a http.md document')
|
.description('Run a http.md document')
|
||||||
.option('-f, --format <format>', 'output format (html, markdown)')
|
|
||||||
.option('-w, --watch', 'watch for changes')
|
.option('-w, --watch', 'watch for changes')
|
||||||
.option('-i, --input <input...>', 'input variables (-i foo=bar -i baz=qux)')
|
.option('-i, --input <input...>', 'input variables (-i foo=bar -i baz=qux)')
|
||||||
.action(async (name, output, options) => {
|
.action(async (name, output, options) => {
|
||||||
const {
|
const {
|
||||||
watch = false,
|
watch = false,
|
||||||
input: i = [],
|
input: i = [],
|
||||||
format = 'markdown',
|
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
|
|
||||||
@@ -102,15 +91,7 @@ program
|
|||||||
context,
|
context,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (format === 'html') {
|
await writeFile(output, result.markdown);
|
||||||
const marked = new Marked();
|
|
||||||
const html = await marked.parse(result.markdown);
|
|
||||||
await writeFile(output, wrapBody(html));
|
|
||||||
} else if (format === 'markdown') {
|
|
||||||
await writeFile(output, result.markdown);
|
|
||||||
} else {
|
|
||||||
throw new Error('Invalid format');
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
...result,
|
...result,
|
||||||
context,
|
context,
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
import blessed from 'blessed';
|
|
||||||
import chalk from 'chalk';
|
|
||||||
|
|
||||||
class UI {
|
|
||||||
#box: blessed.Widgets.BoxElement;
|
|
||||||
#screen: blessed.Widgets.Screen;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
const screen = blessed.screen({
|
|
||||||
smartCSR: true,
|
|
||||||
title: 'Markdown Viewer'
|
|
||||||
});
|
|
||||||
const scrollableBox = blessed.box({ // Or blessed.scrollablebox
|
|
||||||
parent: screen,
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
content: '',
|
|
||||||
scrollable: true,
|
|
||||||
alwaysScroll: true,
|
|
||||||
keys: true,
|
|
||||||
vi: true, // vi-like keybindings
|
|
||||||
mouse: true,
|
|
||||||
scrollbar: {
|
|
||||||
ch: ' ',
|
|
||||||
track: {
|
|
||||||
bg: 'cyan'
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
inverse: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
fg: 'white',
|
|
||||||
bg: 'black'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.#box = scrollableBox;
|
|
||||||
this.#screen = screen;
|
|
||||||
|
|
||||||
screen.key(['escape', 'q', 'C-c'], () => {
|
|
||||||
return process.exit(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
scrollableBox.focus();
|
|
||||||
screen.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
public get screen() {
|
|
||||||
return this.#screen;
|
|
||||||
}
|
|
||||||
|
|
||||||
public set content(content: string) {
|
|
||||||
const originalLines = content.split('\n');
|
|
||||||
const maxLineNoDigits = String(originalLines.length).length; // For padding
|
|
||||||
|
|
||||||
const linesWithNumbers = originalLines.map((line, index) => {
|
|
||||||
const lineNumber = String(index + 1).padStart(maxLineNoDigits, ' ');
|
|
||||||
const styledLineNumber = chalk.dim.yellow(`${lineNumber} | `);
|
|
||||||
return `${styledLineNumber}${line}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
const contentWithLineNumbers = linesWithNumbers.join('\n');
|
|
||||||
this.#box.setContent(contentWithLineNumbers);
|
|
||||||
this.#screen.render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { UI };
|
|
||||||
@@ -10,7 +10,6 @@ type Response = {
|
|||||||
statusText: string;
|
statusText: string;
|
||||||
headers: Record<string, string>;
|
headers: Record<string, string>;
|
||||||
body?: string;
|
body?: string;
|
||||||
rawBody?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type AddRequestOptios = {
|
type AddRequestOptios = {
|
||||||
|
|||||||
@@ -5,12 +5,18 @@ import remarkParse from 'remark-parse'
|
|||||||
import remarkRehype from 'remark-rehype'
|
import remarkRehype from 'remark-rehype'
|
||||||
import remarkDirective from 'remark-directive'
|
import remarkDirective from 'remark-directive'
|
||||||
import remarkStringify from 'remark-stringify'
|
import remarkStringify from 'remark-stringify'
|
||||||
import behead from 'remark-behead';
|
|
||||||
import { unified } from 'unified'
|
import { unified } from 'unified'
|
||||||
import { visit } from 'unist-util-visit'
|
import { visit } from 'unist-util-visit'
|
||||||
|
|
||||||
import { Context } from "../context/context.js";
|
import { Context } from "../context/context.js";
|
||||||
import { handlers, postHandlers } from './handlers/handlers.js';
|
import { handlers } from './handlers/handlers.js';
|
||||||
|
|
||||||
|
const parser = unified()
|
||||||
|
.use(remarkParse)
|
||||||
|
.use(remarkGfm)
|
||||||
|
.use(remarkDirective)
|
||||||
|
.use(remarkStringify)
|
||||||
|
.use(remarkRehype);
|
||||||
|
|
||||||
type BaseNode = {
|
type BaseNode = {
|
||||||
type: string;
|
type: string;
|
||||||
@@ -47,7 +53,6 @@ type ExecutionHandler = (options: {
|
|||||||
|
|
||||||
type ExexutionExecuteOptions = {
|
type ExexutionExecuteOptions = {
|
||||||
context: Context;
|
context: Context;
|
||||||
behead?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const execute = async (file: string, options: ExexutionExecuteOptions) => {
|
const execute = async (file: string, options: ExexutionExecuteOptions) => {
|
||||||
@@ -56,16 +61,6 @@ const execute = async (file: string, options: ExexutionExecuteOptions) => {
|
|||||||
const content = await readFile(file, 'utf-8');
|
const content = await readFile(file, 'utf-8');
|
||||||
const steps: Set<ExecutionStep> = new Set();
|
const steps: Set<ExecutionStep> = new Set();
|
||||||
|
|
||||||
|
|
||||||
const parser = unified()
|
|
||||||
.use(remarkParse)
|
|
||||||
.use(remarkGfm)
|
|
||||||
.use(remarkDirective)
|
|
||||||
.use(remarkStringify)
|
|
||||||
.use(remarkRehype)
|
|
||||||
.use(behead, {
|
|
||||||
depth: options.behead,
|
|
||||||
});
|
|
||||||
const root = parser.parse(content);
|
const root = parser.parse(content);
|
||||||
|
|
||||||
visit(root, (node, index, parent) => {
|
visit(root, (node, index, parent) => {
|
||||||
@@ -80,18 +75,6 @@ const execute = async (file: string, options: ExexutionExecuteOptions) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
visit(root, (node, index, parent) => {
|
|
||||||
for (const handler of postHandlers) {
|
|
||||||
handler({
|
|
||||||
addStep: (step) => steps.add(step),
|
|
||||||
node: node as BaseNode,
|
|
||||||
root,
|
|
||||||
parent: parent as BaseNode | undefined,
|
|
||||||
index,
|
|
||||||
file,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const step of steps) {
|
for (const step of steps) {
|
||||||
const { node, action } = step;
|
const { node, action } = step;
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ const httpHandler: ExecutionHandler = ({
|
|||||||
const content = template(context);
|
const content = template(context);
|
||||||
const [head, body] = content.split('\n\n');
|
const [head, body] = content.split('\n\n');
|
||||||
const [top, ...headerItems] = head.split('\n');
|
const [top, ...headerItems] = head.split('\n');
|
||||||
const [method, ...urlParts] = top.split(' ');
|
const [method, url] = top.split(' ');
|
||||||
const url = urlParts.join(' ').trim();
|
|
||||||
|
|
||||||
const headers = Object.fromEntries(
|
const headers = Object.fromEntries(
|
||||||
headerItems.map((header) => {
|
headerItems.map((header) => {
|
||||||
@@ -44,7 +43,7 @@ const httpHandler: ExecutionHandler = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
let parsedBody = body;
|
let parsedBody = body;
|
||||||
if (options.yaml) {
|
if (options.format === 'yaml') {
|
||||||
try {
|
try {
|
||||||
const parsed = YAML.parse(body);
|
const parsed = YAML.parse(body);
|
||||||
parsedBody = JSON.stringify(parsed);
|
parsedBody = JSON.stringify(parsed);
|
||||||
@@ -59,8 +58,7 @@ const httpHandler: ExecutionHandler = ({
|
|||||||
body
|
body
|
||||||
});
|
});
|
||||||
|
|
||||||
const rawBody = await response.text();
|
let responseText = await response.text();
|
||||||
let responseText = rawBody;
|
|
||||||
if (options.json) {
|
if (options.json) {
|
||||||
try {
|
try {
|
||||||
responseText = JSON.parse(responseText);
|
responseText = JSON.parse(responseText);
|
||||||
@@ -69,7 +67,7 @@ const httpHandler: ExecutionHandler = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node.value = [head, parsedBody].filter(Boolean).join('\n\n');
|
node.value = content;
|
||||||
node.meta = undefined;
|
node.meta = undefined;
|
||||||
|
|
||||||
context.addRequest({
|
context.addRequest({
|
||||||
@@ -85,7 +83,6 @@ const httpHandler: ExecutionHandler = ({
|
|||||||
statusText: response.statusText,
|
statusText: response.statusText,
|
||||||
headers: Object.fromEntries(response.headers.entries()),
|
headers: Object.fromEntries(response.headers.entries()),
|
||||||
body: responseText,
|
body: responseText,
|
||||||
rawBody: rawBody,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ const fileHandler: ExecutionHandler = ({
|
|||||||
}
|
}
|
||||||
const { root: newRoot } = await execute(filePath, {
|
const { root: newRoot } = await execute(filePath, {
|
||||||
context,
|
context,
|
||||||
behead: node.attributes?.behead ? parseInt(node.attributes.behead) : undefined,
|
|
||||||
});
|
});
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
throw new Error('Parent node is required');
|
throw new Error('Parent node is required');
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ const responseHandler: ExecutionHandler = ({
|
|||||||
|
|
||||||
const codeNode = {
|
const codeNode = {
|
||||||
type: 'code',
|
type: 'code',
|
||||||
lang: 'http',
|
|
||||||
value: responseContent,
|
value: responseContent,
|
||||||
};
|
};
|
||||||
if (!parent || !('children' in parent) || index === undefined) {
|
if (!parent || !('children' in parent) || index === undefined) {
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
import { toc } from 'mdast-util-toc';
|
|
||||||
import { type ExecutionHandler } from '../execution.js';
|
|
||||||
|
|
||||||
const tocHandler: ExecutionHandler = ({
|
|
||||||
addStep,
|
|
||||||
node,
|
|
||||||
root,
|
|
||||||
parent,
|
|
||||||
index,
|
|
||||||
}) => {
|
|
||||||
if (node.type === 'leafDirective' && node.name === 'toc') {
|
|
||||||
addStep({
|
|
||||||
type: 'toc',
|
|
||||||
node,
|
|
||||||
action: async () => {
|
|
||||||
const result = toc(root, {
|
|
||||||
tight: true,
|
|
||||||
minDepth: 2,
|
|
||||||
})
|
|
||||||
if (!parent || !parent.children || index === undefined) {
|
|
||||||
throw new Error('Parent node is not valid');
|
|
||||||
}
|
|
||||||
parent.children.splice(index, 1, result.map as any);
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { tocHandler };
|
|
||||||
@@ -6,7 +6,6 @@ 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";
|
import { codeHandler } from "./handlers.code.js";
|
||||||
import { tocHandler } from "./handlers.toc.js";
|
|
||||||
|
|
||||||
const handlers = [
|
const handlers = [
|
||||||
fileHandler,
|
fileHandler,
|
||||||
@@ -18,8 +17,4 @@ const handlers = [
|
|||||||
codeHandler,
|
codeHandler,
|
||||||
] satisfies ExecutionHandler[];
|
] satisfies ExecutionHandler[];
|
||||||
|
|
||||||
const postHandlers = [
|
export { handlers };
|
||||||
tocHandler,
|
|
||||||
] satisfies ExecutionHandler[];
|
|
||||||
|
|
||||||
export { handlers, postHandlers };
|
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
const wrapBody = (body: string) => {
|
|
||||||
return `<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.8.1/github-markdown.min.css" />
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Document</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.markdown-body {
|
|
||||||
max-width: 800px;
|
|
||||||
padding: 20px;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<article class="markdown-body">
|
|
||||||
${body}
|
|
||||||
</article>
|
|
||||||
</body>
|
|
||||||
</html>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
export { wrapBody };
|
|
||||||
Reference in New Issue
Block a user