├── .github
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── config.yaml
│ └── feature_request.md
├── SECURITY.md
└── workflows
│ ├── release-executable.yaml
│ ├── release-npm.yaml
│ ├── release-pypi.yaml
│ └── scripts
│ └── install-rust.sh
├── .gitignore
├── .vscode
├── extensions.json
└── settings.json
├── Cargo.lock
├── Cargo.toml
├── LICENSE
├── README.md
├── benches
└── benchmark.rs
├── build.rs
├── docs
├── BINDINGS_FOR_PYTHON.md
├── executable.md
└── functions.md
├── examples
└── trial.rs
├── napi
├── DEVELOPMENT.md
├── README.md
├── __test__
│ └── index.spec.mjs
├── index.d.ts
├── index.js
├── package-lock.json
├── package.json
└── scripts
│ └── runner.js
├── pyproject.toml
├── src
├── elements
│ ├── consts.rs
│ ├── element.rs
│ ├── mod.rs
│ ├── tags
│ │ ├── general_purpose.rs
│ │ ├── heading.rs
│ │ ├── link.rs
│ │ ├── list.rs
│ │ ├── media.rs
│ │ ├── mod.rs
│ │ ├── preformatted.rs
│ │ ├── table.rs
│ │ └── text_content.rs
│ ├── types.rs
│ └── utils.rs
├── lib.rs
├── main.rs
├── nodejs_bindings.rs
├── nodes
│ ├── mod.rs
│ ├── node.rs
│ └── utils.rs
├── python_bindings.rs
└── utils
│ ├── file.rs
│ └── mod.rs
└── tests
├── fixtures
└── simple-01.html
├── test.rs
└── tmp
└── .gitkeep
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## 🤝 Code of Conduct
2 |
3 | This project is maintained by volunteers in their personal time. We welcome respectful and constructive participation. Please be kind and patient in all interactions.
4 |
5 | As contributors and maintainers, we aim to:
6 |
7 | - Work together with empathy and cooperation
8 | - Strive to understand each other’s intentions
9 | - Exchange ideas constructively to improve the project
10 | - Treat each other with kindness, especially in disagreement
11 |
12 | Thank you for helping us keep the space friendly and focused.
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## ✨ Contributing
2 |
3 | We’re happy to receive feedback, bug reports, and questions via GitHub Issues.
4 | Pull requests are also welcome — though please note that we may not always be able to accept them.
5 |
6 | This project is maintained as a labor of love. We welcome community participation, but:
7 |
8 | - Issues that are respectful and constructive are appreciated.
9 | - Pull requests are reviewed, but acceptance is not guaranteed.
10 | - We do not engage in long debates or vision disagreements.
11 | - If you have a different direction in mind, please fork freely, provided proper licensing is respected.
12 |
13 | Thanks for understanding the scope and spirit of the project.
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug Report
3 | about: Something isn't working as expected
4 | title: "[Bug] "
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Run '...'
17 | 3. See error
18 |
19 | **Expected behavior**
20 | What you expected to happen.
21 |
22 | **Environment (please complete the following information):**
23 | - OS: [e.g. Linux/macOS/Windows]
24 | - Version of this software
25 | - How you started the server (command/flags)
26 |
27 | **Additional context**
28 | Add any other context, logs, or screenshots about the problem here.
29 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yaml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Questions / Feedback
4 | url: https://github.com/nabbisen/apimock-rs
5 | about: Ask questions or leave general feedback here.
6 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature Request
3 | about: Suggest an idea for this project
4 | title: "[Feature] "
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is.
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | Any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or use cases for this feature.
21 |
--------------------------------------------------------------------------------
/.github/SECURITY.md:
--------------------------------------------------------------------------------
1 | ## 🛡️ Security Policy
2 |
3 | ### Reporting a Vulnerability
4 |
5 | If you discover a potential security issue or vulnerability in this software, **please do not create a public issue**.
6 |
7 | Instead, kindly report it privately by sending an [email 📧](nabbisen@scqr.net])
8 |
9 | We will do our best to assess and respond in a timely manner, but please understand that this project is maintained voluntarily in free time. Thank you for your understanding and responsible disclosure.
10 |
11 | ### Supported Versions
12 |
13 | This project is currently maintained as a best-effort activity. Only the latest version is considered to receive potential fixes.
14 |
--------------------------------------------------------------------------------
/.github/workflows/release-executable.yaml:
--------------------------------------------------------------------------------
1 | name: Executable
2 |
3 | on:
4 | release:
5 | types: [created]
6 |
7 | permissions:
8 | contents: write
9 |
10 | defaults:
11 | run:
12 | shell: bash
13 |
14 | env:
15 | PRODUCT_BASENAME: mdka
16 | TAG: ${{ github.ref_name }} # tag or branch name
17 | JOB_WORKDIR: tmp-${{ github.run_id }} # unique number
18 |
19 | jobs:
20 | build:
21 | runs-on: ${{ matrix.os }}
22 | strategy:
23 | matrix:
24 | include:
25 | - name: Linux-aarch64-musl
26 | target: aarch64-unknown-linux-musl
27 | os: ubuntu-latest
28 | bin_ext:
29 | archive_ext: .tar.gz
30 | - name: Linux-x64-gnu
31 | target: x86_64-unknown-linux-gnu
32 | os: ubuntu-latest
33 | bin_ext:
34 | archive_ext: .tar.gz
35 | - name: Linux-x64-musl
36 | target: x86_64-unknown-linux-musl
37 | os: ubuntu-latest
38 | bin_ext:
39 | archive_ext: .tar.gz
40 | - name: macOS-aarch64
41 | target: aarch64-apple-darwin
42 | os: macos-latest
43 | bin_ext:
44 | archive_ext: .zip
45 | - name: Windows-x64
46 | target: x86_64-pc-windows-msvc
47 | os: windows-latest
48 | bin_ext: .exe
49 | archive_ext: .zip
50 |
51 | steps:
52 | - name: Checkout repository
53 | uses: actions/checkout@v4
54 |
55 | # [ build ]
56 | - name: Install Rust
57 | run: bash .github/workflows/scripts/install-rust.sh stable ${{ matrix.target }}
58 |
59 | - name: Cache cargo dependencies and build
60 | uses: actions/cache@v4
61 | with:
62 | path: |
63 | ~/.cargo/registry
64 | ~/.cargo/git
65 | target
66 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
67 | restore-keys: |
68 | ${{ runner.os }}-cargo-
69 |
70 | - name: Build Rust executable
71 | run: |
72 | cargo build --release --target ${{ matrix.target }} --bin ${{ env.PRODUCT_BASENAME }} --locked
73 |
74 | # [ release asset ]
75 | - name: Prepare for release asset
76 | run: |
77 | BUILT_FILEPATH=target/${{ matrix.target }}/release/${{ env.PRODUCT_BASENAME }}${{ matrix.bin_ext }}
78 | RELEASE_ASSET_BASENAME=${{ env.PRODUCT_BASENAME }}@${{ matrix.name }}-${{ env.TAG }}
79 | RELEASE_SRC_DIR=${RELEASE_ASSET_BASENAME}
80 | RELEASE_ASSET_FILENAME=${RELEASE_ASSET_BASENAME}${{ matrix.archive_ext }}
81 | mkdir -p "${{ env.JOB_WORKDIR }}/${RELEASE_SRC_DIR}"
82 | mv "${BUILT_FILEPATH}" "${{ env.JOB_WORKDIR }}/${RELEASE_SRC_DIR}/"
83 | echo "RELEASE_SRC_DIR=${RELEASE_SRC_DIR}" >> $GITHUB_ENV
84 | echo "RELEASE_ASSET_FILENAME=${RELEASE_ASSET_FILENAME}" >> $GITHUB_ENV
85 |
86 | # BSD tar on macOS: first 8MB of the file are sometimes all NUL byte
87 | # refs: https://github.com/actions/cache/issues/403 , https://github.com/rust-lang/cargo/issues/8603
88 | - name: Mitigate macOS tar bug
89 | if: matrix.target == 'aarch64-apple-darwin'
90 | run: |
91 | sudo /usr/sbin/purge
92 |
93 | - name: Create archive as release asset - Linux
94 | if: >
95 | matrix.target != 'aarch64-apple-darwin' &&
96 | matrix.target != 'x86_64-pc-windows-msvc'
97 | run: |
98 | cd "${{ env.JOB_WORKDIR }}"
99 | tar czf "../${RELEASE_ASSET_FILENAME}" "${RELEASE_SRC_DIR}"
100 |
101 | - name: Create archive as release asset - Windows / macOS
102 | if: >
103 | matrix.target == 'aarch64-apple-darwin' ||
104 | matrix.target == 'x86_64-pc-windows-msvc'
105 | run: |
106 | cd "${{ env.JOB_WORKDIR }}"
107 | 7z a "../${RELEASE_ASSET_FILENAME}" "${RELEASE_SRC_DIR}"
108 |
109 | - name: Update release with new asset
110 | env:
111 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
112 | run: gh release upload ${{ github.ref_name }} ${RELEASE_ASSET_FILENAME}
113 |
--------------------------------------------------------------------------------
/.github/workflows/release-npm.yaml:
--------------------------------------------------------------------------------
1 | name: npm
2 |
3 | on:
4 | release:
5 | types: [created]
6 |
7 | permissions:
8 | contents: write
9 | id-token: write
10 |
11 | defaults:
12 | run:
13 | shell: bash
14 |
15 | env:
16 | PRODUCT_BASENAME: mdka
17 | TAG: ${{ github.ref_name }} # tag or branch name
18 | JOB_WORKDIR: tmp-${{ github.run_id }} # unique number
19 |
20 | jobs:
21 | build:
22 | runs-on: ${{ matrix.os }}
23 | strategy:
24 | matrix:
25 | include:
26 | - name: Linux-x64-gnu
27 | target: x86_64-unknown-linux-gnu
28 | os: ubuntu-latest
29 | archive_ext: .tar.gz
30 | napiplatform: linux-x64-gnu
31 | - name: macOS-aarch64
32 | target: aarch64-apple-darwin
33 | os: macos-latest
34 | archive_ext: .zip
35 | napiplatform: darwin-arm64
36 | - name: Windows-x64
37 | target: x86_64-pc-windows-msvc
38 | os: windows-latest
39 | archive_ext: .zip
40 | napiplatform: win32-x64-msvc
41 |
42 | steps:
43 | - name: Checkout repository
44 | uses: actions/checkout@v4
45 |
46 | # [ Node.js dependencies ]
47 | - name: Prepare napi
48 | run: cp -r napi/* .
49 | # todo: better ? to replace w/
50 | # working-directory: napi
51 |
52 | - name: Setup Node.js
53 | uses: actions/setup-node@v4
54 | with:
55 | node-version: 22
56 | cache: npm
57 |
58 | - name: Install npm packages
59 | run: npm install
60 |
61 | # [ build ]
62 | - name: Install Rust
63 | run: bash .github/workflows/scripts/install-rust.sh stable ${{ matrix.target }}
64 |
65 | - name: Cache cargo dependencies and build
66 | uses: actions/cache@v4
67 | with:
68 | path: |
69 | ~/.cargo/registry
70 | ~/.cargo/git
71 | target
72 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
73 | restore-keys: |
74 | ${{ runner.os }}-cargo-
75 |
76 | - name: Build Rust executable
77 | run: |
78 | npm run build
79 |
80 | # [ release asset ]
81 | - name: Upload artifact
82 | uses: actions/upload-artifact@v4
83 | with:
84 | name: bindings-${{ matrix.target }}
85 | path: ${{ env.PRODUCT_BASENAME }}.*.node
86 | if-no-files-found: error
87 |
88 | publish:
89 | name: Publish on release tags
90 | needs:
91 | - build
92 | runs-on: ubuntu-latest
93 | steps:
94 | - name: Check if release tag
95 | run: |
96 | if [[ "${TAG}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || \
97 | [[ "${TAG}" =~ ^[0-9]+\.[0-9]+\.[0-9]-rc\.[0-9]+$ ]]; then
98 | echo "${TAG}: Semantic versioning tagged - OK"
99 | else
100 | echo "Not a release tag. Skipped."
101 | exit 1
102 | fi
103 |
104 | - uses: actions/checkout@v4
105 |
106 | - name: Prepare napi
107 | run: cp -r napi/* .
108 | # todo: better ? to replace w/
109 | # working-directory: napi
110 |
111 | - name: Setup node
112 | uses: actions/setup-node@v4
113 | with:
114 | node-version: 22
115 | cache: npm
116 |
117 | - name: Install dependencies
118 | run: npm install
119 |
120 | - name: Download all artifacts
121 | uses: actions/download-artifact@v4
122 | with:
123 | path: artifacts
124 |
125 | - name: Move artifacts
126 | run: |
127 | npm run create-npm-dir
128 | npm run artifacts
129 |
130 | - name: List packages
131 | run: ls -R ./npm
132 | shell: bash
133 |
134 | - name: Publish
135 | env:
136 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
137 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
138 | run: |
139 | npm config set provenance true
140 | echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
141 | npm publish --access public
142 |
--------------------------------------------------------------------------------
/.github/workflows/release-pypi.yaml:
--------------------------------------------------------------------------------
1 | # Modified:
2 | # This file is autogenerated by maturin v1.8.2
3 | # To update, run
4 | #
5 | # maturin generate-ci github
6 | #
7 | name: PyPi
8 |
9 | on:
10 | release:
11 | types: [created]
12 |
13 | permissions:
14 | contents: read
15 |
16 | jobs:
17 | linux:
18 | runs-on: ${{ matrix.platform.runner }}
19 | strategy:
20 | matrix:
21 | platform:
22 | - runner: ubuntu-latest
23 | target: x86_64
24 | - runner: ubuntu-latest
25 | target: aarch64
26 | steps:
27 | - uses: actions/checkout@v4
28 | - uses: actions/setup-python@v5
29 | with:
30 | python-version: 3.x
31 |
32 | - name: Cache cargo dependencies and build
33 | uses: actions/cache@v4
34 | with:
35 | path: |
36 | ~/.cargo/registry
37 | ~/.cargo/git
38 | target
39 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
40 | restore-keys: |
41 | ${{ runner.os }}-cargo-
42 |
43 | - name: Build wheels
44 | uses: PyO3/maturin-action@v1
45 | with:
46 | target: ${{ matrix.platform.target }}
47 | args: --release --out dist --find-interpreter -F pyo3
48 | sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
49 | manylinux: auto
50 | - name: Upload wheels
51 | uses: actions/upload-artifact@v4
52 | with:
53 | name: wheels-linux-${{ matrix.platform.target }}
54 | path: dist
55 |
56 | musllinux:
57 | runs-on: ${{ matrix.platform.runner }}
58 | strategy:
59 | matrix:
60 | platform:
61 | - runner: ubuntu-latest
62 | target: x86_64
63 | - runner: ubuntu-latest
64 | target: aarch64
65 | steps:
66 | - uses: actions/checkout@v4
67 | - uses: actions/setup-python@v5
68 | with:
69 | python-version: 3.x
70 |
71 | - name: Cache cargo dependencies and build
72 | uses: actions/cache@v4
73 | with:
74 | path: |
75 | ~/.cargo/registry
76 | ~/.cargo/git
77 | target
78 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
79 | restore-keys: |
80 | ${{ runner.os }}-cargo-
81 |
82 | - name: Build wheels
83 | uses: PyO3/maturin-action@v1
84 | with:
85 | target: ${{ matrix.platform.target }}
86 | args: --release --out dist --find-interpreter -F pyo3
87 | sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
88 | manylinux: musllinux_1_2
89 | - name: Upload wheels
90 | uses: actions/upload-artifact@v4
91 | with:
92 | name: wheels-musllinux-${{ matrix.platform.target }}
93 | path: dist
94 |
95 | windows:
96 | runs-on: ${{ matrix.platform.runner }}
97 | strategy:
98 | matrix:
99 | platform:
100 | - runner: windows-latest
101 | target: x64
102 | steps:
103 | - uses: actions/checkout@v4
104 | - uses: actions/setup-python@v5
105 | with:
106 | python-version: 3.x
107 | architecture: ${{ matrix.platform.target }}
108 |
109 | - name: Cache cargo dependencies and build
110 | uses: actions/cache@v4
111 | with:
112 | path: |
113 | ~/.cargo/registry
114 | ~/.cargo/git
115 | target
116 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
117 | restore-keys: |
118 | ${{ runner.os }}-cargo-
119 |
120 | - name: Build wheels
121 | uses: PyO3/maturin-action@v1
122 | with:
123 | target: ${{ matrix.platform.target }}
124 | args: --release --out dist --find-interpreter -F pyo3
125 | sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
126 | - name: Upload wheels
127 | uses: actions/upload-artifact@v4
128 | with:
129 | name: wheels-windows-${{ matrix.platform.target }}
130 | path: dist
131 |
132 | macos:
133 | runs-on: ${{ matrix.platform.runner }}
134 | strategy:
135 | matrix:
136 | platform:
137 | - runner: macos-latest
138 | target: aarch64
139 | steps:
140 | - uses: actions/checkout@v4
141 | - uses: actions/setup-python@v5
142 | with:
143 | python-version: 3.x
144 |
145 | - name: Cache cargo dependencies and build
146 | uses: actions/cache@v4
147 | with:
148 | path: |
149 | ~/.cargo/registry
150 | ~/.cargo/git
151 | target
152 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
153 | restore-keys: |
154 | ${{ runner.os }}-cargo-
155 |
156 | - name: Build wheels
157 | uses: PyO3/maturin-action@v1
158 | with:
159 | target: ${{ matrix.platform.target }}
160 | args: --release --out dist --find-interpreter -F pyo3
161 | sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
162 | - name: Upload wheels
163 | uses: actions/upload-artifact@v4
164 | with:
165 | name: wheels-macos-${{ matrix.platform.target }}
166 | path: dist
167 |
168 | sdist:
169 | runs-on: ubuntu-latest
170 | steps:
171 | - uses: actions/checkout@v4
172 | - name: Build sdist
173 | uses: PyO3/maturin-action@v1
174 | with:
175 | command: sdist
176 | args: --out dist
177 | - name: Upload sdist
178 | uses: actions/upload-artifact@v4
179 | with:
180 | name: wheels-sdist
181 | path: dist
182 |
183 | release:
184 | name: Release
185 | runs-on: ubuntu-latest
186 | if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
187 | needs: [linux, musllinux, windows, macos, sdist]
188 | permissions:
189 | # Use to sign the release artifacts
190 | id-token: write
191 | # Used to upload release artifacts
192 | contents: write
193 | # Used to generate artifact attestation
194 | attestations: write
195 | steps:
196 | - uses: actions/download-artifact@v4
197 | - name: Generate artifact attestation
198 | uses: actions/attest-build-provenance@v1
199 | with:
200 | subject-path: 'wheels-*/*'
201 | - name: Publish to PyPI
202 | if: ${{ startsWith(github.ref, 'refs/tags/') }}
203 | uses: PyO3/maturin-action@v1
204 | env:
205 | MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
206 | with:
207 | command: upload
208 | args: --non-interactive --skip-existing wheels-*/*
209 |
--------------------------------------------------------------------------------
/.github/workflows/scripts/install-rust.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Install/update rust.
3 | # The first argument should be the toolchain to install.
4 |
5 | set -ex
6 | if [ -z "$1" ]
7 | then
8 | echo "First parameter must be toolchain to install."
9 | exit 1
10 | fi
11 | TOOLCHAIN="$1"
12 |
13 | rustup set profile minimal
14 | rustup component remove --toolchain=$TOOLCHAIN rust-docs || echo "already removed"
15 | rustup update --no-self-update $TOOLCHAIN
16 | if [ -n "$2" ]
17 | then
18 | TARGET="$2"
19 | HOST=$(rustc -Vv | grep ^host: | sed -e "s/host: //g")
20 | if [ "$HOST" != "$TARGET" ]
21 | then
22 | rustup component add llvm-tools-preview --toolchain=$TOOLCHAIN
23 | rustup component add rust-std-$TARGET --toolchain=$TOOLCHAIN
24 | fi
25 | if [[ $TARGET == *"musl" ]]
26 | then
27 | # This is needed by libdbus-sys.
28 | sudo apt update -y && sudo apt install musl-dev musl-tools -y
29 | fi
30 | if [[ $TARGET == "aarch64-unknown-linux-musl" ]]
31 | then
32 | echo CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=rust-lld >> $GITHUB_ENV
33 | # This `CC` is some nonsense needed for libdbus-sys (via opener).
34 | # I don't know if this is really the right thing to do, but it seems to work.
35 | sudo apt install gcc-aarch64-linux-gnu -y
36 | echo CC=aarch64-linux-gnu-gcc >> $GITHUB_ENV
37 | fi
38 | fi
39 |
40 | rustup default $TOOLCHAIN
41 | rustup -V
42 | rustc -Vv
43 | cargo -V
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Generated by Cargo
2 | # will have compiled files and executables
3 | debug/
4 | target/
5 |
6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
8 | # Cargo.lock
9 |
10 | # These are backup files generated by rustfmt
11 | **/*.rs.bk
12 |
13 | # MSVC Windows builds of rustc generate these, which store debugging information
14 | *.pdb
15 |
16 | # custom
17 | tests/tmp/*
18 | !tests/tmp/.gitkeep
19 |
20 | # napi
21 | node_modules/
22 | *.node
23 | bun.lock
24 | bun.lockb
25 | .env
26 | .env.*
27 | !.env.example
28 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "rust-lang.rust-analyzer"
4 | ]
5 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true
3 | }
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "mdka"
3 | version = "1.5.0"
4 | edition = "2021"
5 |
6 | description = "HTML to Markdown converter"
7 | authors = ["nabbisen "]
8 | license = "Apache-2.0"
9 | categories = ["development-tools", "parsing", "parser-implementations"]
10 | keywords = ["html", "markdown", "parser", "conversion"]
11 | repository = "https://github.com/nabbisen/mdka-rs"
12 | readme = "README.md"
13 |
14 | rust-version = "1.74.0"
15 |
16 | [lib]
17 | name = "mdka"
18 | crate-type = ["rlib", "cdylib"]
19 |
20 | [profile.release] # shrink executable size
21 | opt-level = "z"
22 | lto = true
23 | # panic = "abort"
24 | strip = true
25 | codegen-units = 1
26 |
27 | [profile.dev] # to reasonably improve productivity
28 | opt-level = 1 # slightly optimize
29 | lto = false # disable link-time optimizations
30 | # strip = "debuginfo" # reduce size
31 | incremental = true
32 |
33 | [features]
34 | default = []
35 | pyo3 = ["dep:pyo3"]
36 | napi = ["dep:napi", "dep:napi-derive", "dep:napi-build"]
37 |
38 | [dependencies]
39 | html5ever = "^0.27"
40 | markup5ever_rcdom = "^0.3"
41 | # binding for python
42 | pyo3 = { version = "0", features = ["extension-module"], optional = true }
43 | # binding for node.js
44 | napi = { version = "2", default-features = false, features = ["napi5", "async"], optional = true }
45 | napi-derive = { version = "2", optional = true }
46 |
47 | [dev-dependencies]
48 | criterion = "0"
49 | maturin = "1"
50 |
51 | [build-dependencies]
52 | napi-build = { version = "2", optional = true }
53 |
54 | [[example]]
55 | name = "trial"
56 | path = "examples/trial.rs"
57 |
58 | [[bench]]
59 | name = "benchmark"
60 | harness = false
61 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # mdka
2 |
3 | **HTML to Markdown (MD)** converter written in [Rust](https://www.rust-lang.org/).
4 |
5 | [](https://crates.io/crates/mdka)
6 | [](https://docs.rs/mdka)
7 | [](https://deps.rs/crate/mdka)
8 | [](https://github.com/nabbisen/mdka-rs/actions/workflows/release-executable.yaml)
9 | [](https://github.com/nabbisen/mdka-rs/actions/workflows/release-pypi.yaml)
10 | [](https://github.com/nabbisen/mdka-rs/blob/main/LICENSE)
11 |
12 | ## Summary
13 |
14 | A kind of text manipulator named mdka. "ka" means "化 (か)" pointing to conversion.
15 | Designed with in mind:
16 |
17 | - Fast speed
18 | - Low memory consumption
19 | - Easy usage
20 |
21 | ## Usage
22 |
23 | ### 🌠 Rust with cargo
24 |
25 | ```toml
26 | # Cargo.toml
27 | [dependencies]
28 | mdka = "1"
29 | ```
30 |
31 | ```rust
32 | // awesome.rs
33 | use mdka::from_html
34 |
35 | fn awesome_fn() {
36 | let input = r#"
37 |