{"id":51243583,"url":"https://github.com/vinicq/md-bridge","last_synced_at":"2026-06-29T02:09:02.626Z","repository":{"id":360292081,"uuid":"1243802208","full_name":"vinicq/md-bridge","owner":"vinicq","description":"Self-hosted document converter built on hand-written heuristics, not language models. Ships PDF ↔ Markdown; the architecture welcomes new format pairs as contributions land. Deterministic by design: same input, same output, every run. FastAPI + React, multi-arch Docker, MIT.","archived":false,"fork":false,"pushed_at":"2026-06-18T21:39:35.000Z","size":15443,"stargazers_count":4,"open_issues_count":34,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-18T23:16:29.398Z","etag":null,"topics":["chromium","converter","deterministic","docker","document-converter","fastapi","local-first","markdown","mkdocs","pdf","playwright","pymupdf","react","self-hosted","typescript"],"latest_commit_sha":null,"homepage":"https://vinicq.github.io/md-bridge/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vinicq.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-19T17:18:16.000Z","updated_at":"2026-06-18T21:25:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/vinicq/md-bridge","commit_stats":null,"previous_names":["vinicq/md-bridge"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/vinicq/md-bridge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinicq%2Fmd-bridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinicq%2Fmd-bridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinicq%2Fmd-bridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinicq%2Fmd-bridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vinicq","download_url":"https://codeload.github.com/vinicq/md-bridge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinicq%2Fmd-bridge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34910349,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-29T02:00:05.398Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chromium","converter","deterministic","docker","document-converter","fastapi","local-first","markdown","mkdocs","pdf","playwright","pymupdf","react","self-hosted","typescript"],"created_at":"2026-06-29T02:09:01.451Z","updated_at":"2026-06-29T02:09:02.609Z","avatar_url":"https://github.com/vinicq.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/brand/wordmark.png\" alt=\"md-bridge\" width=\"600\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eSelf-hosted PDF ↔ Markdown converter.\u003c/strong\u003e\u003cbr\u003e\n  Deterministic, heuristic, no external calls.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/vinicq/md-bridge/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/vinicq/md-bridge/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/vinicq/md-bridge/actions/workflows/codeql.yml\"\u003e\u003cimg src=\"https://github.com/vinicq/md-bridge/actions/workflows/codeql.yml/badge.svg\" alt=\"CodeQL\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://scorecard.dev/viewer/?uri=github.com/vinicq/md-bridge\"\u003e\u003cimg src=\"https://api.scorecard.dev/projects/github.com/vinicq/md-bridge/badge\" alt=\"OpenSSF Scorecard\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.python.org/downloads/\"\u003e\u003cimg src=\"https://img.shields.io/badge/python-3.12%2B-blue.svg\" alt=\"Python 3.12+\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://nodejs.org/\"\u003e\u003cimg src=\"https://img.shields.io/badge/node-22%2B-43853d.svg\" alt=\"Node 22+\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-green.svg\" alt=\"License: MIT\"\u003e\u003c/a\u003e\n  \u003ca href=\"#testing\"\u003e\u003cimg src=\"https://img.shields.io/badge/tests-124%20total-brightgreen.svg\" alt=\"Tests\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/vinicq/md-bridge\"\u003e\u003cimg src=\"https://codecov.io/gh/vinicq/md-bridge/graph/badge.svg\" alt=\"Coverage\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  📖 \u003ca href=\"https://vinicq.github.io/md-bridge/\"\u003eDocumentation site\u003c/a\u003e\n  \u0026nbsp;·\u0026nbsp;\n  🐳 \u003ca href=\"https://github.com/vinicq/md-bridge/pkgs/container/md-bridge-api\"\u003eDocker images on GHCR\u003c/a\u003e\n  \u0026nbsp;·\u0026nbsp;\n  📝 \u003ca href=\"CHANGELOG.md\"\u003eChangelog\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003csub\u003e\n    \u003ca href=\"https://vinicq.github.io/md-bridge/architecture/\"\u003eArchitecture\u003c/a\u003e\n    \u0026nbsp;·\u0026nbsp;\n    \u003ca href=\"https://vinicq.github.io/md-bridge/heuristics/\"\u003eHeuristics\u003c/a\u003e\n    \u0026nbsp;·\u0026nbsp;\n    \u003ca href=\"https://vinicq.github.io/md-bridge/faq/\"\u003eFAQ\u003c/a\u003e\n    \u0026nbsp;·\u0026nbsp;\n    \u003ca href=\"https://vinicq.github.io/md-bridge/api-recipes/\"\u003eAPI recipes\u003c/a\u003e\n    \u0026nbsp;·\u0026nbsp;\n    \u003ca href=\"https://vinicq.github.io/md-bridge/deployment-other/\"\u003eDeploy recipes\u003c/a\u003e\n  \u003c/sub\u003e\n\u003c/p\u003e\n\n---\n\n![Demo of the conversion UI](docs/screenshots/demo.gif)\n\n`md-bridge` is a self-hosted document converter built on hand-written\nheuristics: same input, same output, every run. PyMuPDF reads PDFs, headless\nChromium renders Markdown back into print-ready PDFs, FastAPI ties it all\ntogether, and a small React app drives the whole thing from the browser.\n\nThe first release ships PDF ↔ Markdown. The architecture is built to\nwelcome new format pairs as contributions land: DOCX, EPUB, RTF, and\nothers are natural fits behind the same heuristic-pipeline pattern.\n\n---\n\n## Table of contents\n\n- [Highlights](#highlights)\n- [Demo flow](#demo-flow)\n- [Tech stack](#tech-stack)\n- [Quickstart](#quickstart)\n- [Run with Docker](#run-with-docker)\n- [Project layout](#project-layout)\n- [Running it](#running-it)\n- [Testing](#testing)\n- [API reference](#api-reference)\n- [Screenshots](#screenshots)\n- [Internationalization](#internationalization)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Highlights\n\n- **PDF to Markdown** with heading detection (font size plus PDF outline), list\n  recovery (bullet glyphs and numbered patterns), table extraction via\n  PyMuPDF's `find_tables`, and YAML front matter for metadata.\n- **Markdown to PDF** rendered through headless Chromium (Playwright) using\n  a bundled A4 stylesheet at `packages/markdown-to-pdf/templates/default.css`.\n- **Batch mode**: drop one file or a whole folder. The UI lists every file,\n  converts them in sequence, and lets you download each result as it lands.\n- **`/api/inspect-pdf`** returns diagnostics (fonts, sizes, tagged-PDF flag,\n  OCR hint) so the UI can warn before conversion.\n- **No persistence**, no third-party calls. Every request runs in a\n  temporary directory that is removed before the response goes out.\n- **Multilingual UI** (English by default, Portuguese and Spanish optional) with a header\n  toggle that persists the choice in `localStorage`.\n- **Interactive API docs** at `/docs` (Swagger UI) and `/redoc`, plus a\n  walkthrough in [`docs/API.md`](docs/API.md).\n- **Declared Markdown dialect**: CommonMark 0.31.2 plus a named GFM and Pandoc\n  subset, set in [ADR-001](docs/architecture/adr-001-markdown-dialect.md). Both\n  converters target it, so the output is predictable for downstream tools.\n\n## Demo flow\n\n```\n┌──────────────┐   PDF file   ┌──────────────┐   structured MD   ┌──────────────┐\n│  React UI    │ ───────────▶ │  FastAPI     │ ────────────────▶ │  Browser     │\n│  (Vite)      │              │  /api/...    │                   │  download    │\n└──────┬───────┘              └──────┬───────┘                   └──────────────┘\n       │                              │\n       │       imports (no rewrite)   │\n       ▼                              ▼\n┌────────────────────────────────────────────┐\n│  packages/pdf-to-markdown   (heuristic)    │\n│  packages/markdown-to-pdf   (Chromium)     │\n└────────────────────────────────────────────┘\n```\n\n## Tech stack\n\n| Layer        | Choice                                     |\n| ------------ | ------------------------------------------ |\n| Backend      | FastAPI, Pydantic v2, Uvicorn              |\n| Conversion   | PyMuPDF, pypdf, Python-Markdown, Playwright|\n| Frontend     | Vite, React, TypeScript, React Router 6    |\n| Styling      | Plain CSS with design tokens, no framework |\n| Tests        | pytest, Vitest, React Testing Library, Playwright |\n| i18n         | Lightweight context provider, EN plus PT/ES |\n\n## Quickstart\n\nYou will need:\n\n- Python 3.12 or newer\n- Node 22 and npm 10 or newer\n\nThe commands below work the same on macOS, Linux, and Windows once the\nvirtual environment is activated. Activate scripts differ by shell:\n\n```bash\n# 1. Backend: create the virtual environment\ncd apps/api\npython -m venv .venv\n\n# Activate it (pick the line for your shell):\nsource .venv/bin/activate                   # macOS / Linux / Git Bash\n# .venv\\Scripts\\Activate.ps1                # Windows PowerShell\n\n# Install the backend and the converter dependencies:\npython -m pip install -e \".[dev]\"\npython -m playwright install chromium\n\n# Optional OCR for scanned PDFs (Linux example):\nsudo apt install tesseract-ocr tesseract-ocr-por tesseract-ocr-spa\npython -m pip install -e \".[dev,ocr]\"\n# OCR runs automatically once the stack above is installed, auto-handling\n# English, Portuguese, and Spanish. A lean install without it stays OCR-free\n# and returns 422 ocr_required for a scanned PDF.\n# Optional: export MD_BRIDGE_OCR_ENABLED=0   # force OCR off even when installed\n# Optional: export MD_BRIDGE_OCR_LANG=eng    # pin a single language pack\n\n# Docker: build the OCR-enabled API image target.\ndocker build -f apps/api/Dockerfile --target runtime-ocr -t md-bridge-api:ocr\n\n# 2. Frontend\ncd ../web\nnpm install\nnpx playwright install chromium\n\n# 3. Root-level helper (lets you start API and UI together)\ncd ../..\nnpm install\n\n# 4. Boot the dev servers: API on port 8000, Vite on port 5173\nnpm run dev\n```\n\nOpen `http://localhost:5173` for the UI and `http://localhost:8000/docs`\nfor the interactive API documentation.\n\n## Run with Docker\n\nOne command brings the API and the web UI up together:\n\n```bash\ndocker compose up\n```\n\nTo pull pre-built images from GHCR instead of building locally:\n\n```bash\ndocker pull ghcr.io/vinicq/md-bridge-api:latest\ndocker pull ghcr.io/vinicq/md-bridge-web:latest\n```\n\nEach release also gets pinned tags (`0.1.1`, `0.1`, etc.).\n\n### Deploying to a free cloud VM\n\n`deployment/oracle-cloud/` ships a complete recipe for running md-bridge\non the **Oracle Cloud Always Free** tier (4 OCPU ARM + 24 GB RAM, US$0\nforever). One bootstrap script installs Docker, Caddy, and the stack;\nHTTPS is automatic via Let's Encrypt. See the\n[walkthrough](deployment/oracle-cloud/README.md) or the\n[docs site](https://vinicq.github.io/md-bridge/deployment/oracle-cloud/).\n\nFor a no-VM, click-and-deploy option, see\n[Deploy to Render (free tier)](https://vinicq.github.io/md-bridge/deployment/render/).\nRender reads the existing `render.yaml` blueprint at the repo root and\nmaps it to two services from the public GHCR images.\n\nThe API listens on `http://localhost:8000` and the web UI on\n`http://localhost:5173`. The web container waits for the API healthcheck\nbefore starting, so the first call from the browser already has a live\nbackend behind it.\n\nThe compose stack runs the application, not the test suite by default.\nThe healthchecks on each container only confirm that the service is\nreachable, not that it behaves correctly.\n\nIf you do not have Python or Node installed locally and want to run the\ntests anyway, an opt-in `test` profile spins up ephemeral containers that\nexecute pytest and vitest:\n\n```bash\ndocker compose --profile test run --rm tests-api   # backend pytest\ndocker compose --profile test run --rm tests-web   # frontend vitest\n```\n\nBoth containers exit when the suite finishes; nothing keeps running in\nthe background. Playwright end-to-end tests are not part of the compose\nprofile (they need a real browser session and a running API). They live\nin CI (GitHub Actions, see [`.github/workflows/ci.yml`](.github/workflows/ci.yml))\nand run locally through `npm run test:e2e`.\n\n## Project layout\n\n```\nmd-bridge/\n├── apps/\n│   ├── api/          FastAPI service: routes, services, schemas, tests\n│   └── web/          React app: pages, components, hooks, tests, e2e specs\n├── packages/\n│   ├── pdf-to-markdown/   Vendored converter (PyMuPDF heuristics)\n│   └── markdown-to-pdf/   Vendored renderer (Chromium via Playwright)\n├── tests/            Conversion-layer regression with golden files\n├── docs/\n│   └── API.md        REST walkthrough\n├── docker-compose.yml\n├── package.json      Root scripts (`npm run dev`, `npm run test:all`)\n└── README.md\n```\n\n## Running it\n\n```bash\n# Both servers in parallel (recommended for local dev)\nnpm run dev\n\n# Or one at a time:\nnpm run dev:api           # FastAPI with auto-reload on :8000\nnpm run dev:web           # Vite on :5173 (proxies /api to :8000)\n```\n\nProduction build for the frontend:\n\n```bash\nnpm run build             # writes apps/web/dist/\n```\n\nFor a production API run, drop `--reload` and pin a process manager of your\nchoice. The command assumes the virtual environment is already activated:\n\n```bash\npython -m uvicorn app.main:app --port 8000 --app-dir apps/api\n```\n\n## Testing\n\nThe test suite follows a classic pyramid with 124 tests in total, every one\nof which runs on CI against the committed ISTQB CTAL-TA syllabus fixture. No\nmocks of the API, fetch, or browser primitives: integration runs against the\nreal FastAPI TestClient and E2E drives a real Chromium against a real\nbackend.\n\n| Tier        | Count | What it covers                                                   |\n| ----------- | ----- | ---------------------------------------------------------------- |\n| Unit        | 92    | 46 backend (schemas, helpers, errors, heuristics) + 46 frontend (components, hooks, i18n) |\n| Integration | 26    | 14 backend with FastAPI TestClient + 3 regression goldens + 9 frontend page tests (Home, About, Navigation, batch panel) |\n| E2E         | 6     | Playwright real-browser specs: ISTQB conversion, md-to-pdf, language toggle, batch with two files |\n\nRun them with:\n\n```bash\nnpm run test:unit                   # 46 backend + 46 frontend = 92 unit tests\nnpm run test:unit:api               # backend unit (pytest, apps/api/tests/unit)\nnpm run test:unit:web               # frontend unit (Vitest)\n\nnpm run test:integration            # backend + regression goldens + frontend pages = 26\nnpm run test:integration:api        # FastAPI TestClient (apps/api/tests/integration)\nnpm run test:integration:regression # 3 golden-file regressions (tests/regression)\nnpm run test:integration:web        # frontend page tests (Home, About, Navigation, batch)\n\nnpm run test:e2e                    # 6 Playwright real-browser specs\n\nnpm run test:all                    # everything in sequence\n```\n\nThe integration tier uses a real-world fixture: the ISTQB CTAL-TA EN\nsyllabus (`apps/api/tests/fixtures/istqb-ctal-ta-syllabus-en.pdf`). It\nexercises the heuristic converter against a long, table-heavy, outline-rich\nPDF that is representative of the documents users care about. Every test\nruns against this fixture, so there are no silent skips on CI.\n\nRegression snapshots live under `tests/golden/`. After a deliberate change\nto the heuristics, regenerate them with the virtual environment active:\n\n```bash\npython -m pytest tests/regression --update-golden\n```\n\n## API reference\n\nThe FastAPI app ships with two built-in doc viewers:\n\n- **Swagger UI** (try-it-out playground): `http://localhost:8000/docs`\n- **ReDoc** (long-form reference): `http://localhost:8000/redoc`\n\nA walkthrough with `curl` examples and the full error envelope catalogue\nlives in [`docs/API.md`](docs/API.md).\n\nQuick sample, convert a PDF:\n\n```bash\ncurl -X POST http://localhost:8000/api/pdf-to-md \\\n  -F \"file=@whitepaper.pdf\" \\\n  -F 'options={\"front_matter\": true}'\n```\n\nQuick sample, render Markdown back to PDF:\n\n```bash\ncurl -X POST http://localhost:8000/api/md-to-pdf \\\n  -F \"file=@notes.md\" \\\n  --output notes.pdf\n```\n\n## Screenshots\n\n### Home page across locales\n\n| English | Portuguese | Spanish |\n|---|---|---|\n| ![Home EN](docs/screenshots/home-en.png) | ![Home PT](docs/screenshots/home-pt.png) | ![Home ES](docs/screenshots/home-es.png) |\n\n### Conversion flow\n\n| | |\n|---|---|\n| **PDF to Markdown** (idle) | **Batch mode**, two PDFs queued |\n| ![PDF to MD](docs/screenshots/pdf-to-md.png) | ![Batch](docs/screenshots/pdf-to-md-batch.png) |\n| **Markdown to PDF** flow | **About page** |\n| ![MD to PDF](docs/screenshots/md-to-pdf.png) | ![About](docs/screenshots/about.png) |\n| **Swagger UI** at `/docs` | |\n| ![Swagger](docs/screenshots/swagger.png) | |\n\n## Internationalization\n\nThe UI ships with English (default), Portuguese, and Spanish. The header carries a\nlocale toggle (`EN` / `PT` / `ES`); the choice is persisted in `localStorage`\nunder `md-bridge:locale`.\n\nTo add a new locale:\n\n1. Open `apps/web/src/i18n/dictionaries.ts`.\n2. Add a new entry to the `Locale` union and to the `LOCALES` array.\n3. Translate the `Dictionary` shape and add it to `DICTIONARIES`.\n\nThe header toggle picks the new locale up automatically.\n\n## Design system\n\n![Roadmap of the md-bridge design system: eight features, eight issues, one coherent system](docs/design/screenshots/hero.png)\n\nEvery UI change tracks back to a mockup in\n[`docs/design/`](docs/design/). The catalogue is a single self-contained\nHTML file (`design-thinking.html`) with hi-fi mockups and paste-ready\nissue specs for eight features (CSS theme picker, theme library,\nper-conversion options panel, format hub for DOCX/EPUB/HTML/RTF,\nlanguage workshop, conversion presets, local history, preferences\npage). Published on the docs site under\n[/design/](https://vinicq.github.io/md-bridge/design/), with the live\ncatalogue at\n[/design/design-thinking.html](https://vinicq.github.io/md-bridge/design/design-thinking.html).\n\nOpen issues tagged `design-required` point back at the matching\nF-section. To propose a brand-new UI change, open a feature-request\nissue with a sketch; the maintainer decides whether it slots into an\nexisting F-section or warrants a fresh design pass.\n\n## Limits\n\n- 500 MB cap per upload\n- nginx reverse proxy waits up to 10 minutes per request, which fits very\n  large PDFs end-to-end\n- No OCR yet: scanned PDFs need Tesseract before being submitted\n- Tables with merged cells can be flattened by the heuristic extractor\n\n## Contributing\n\nIssues and pull requests are welcome. UI changes track back to the\n[design system in `docs/design/`](docs/design/) (also published with the\ndocs site); features tagged `design-required` usually have a matching\nmockup there. Read [CONTRIBUTING.md](CONTRIBUTING.md) for the full\nguide; the headline rules are:\n\n- Every behaviour change ships with tests at the lowest viable tier.\n- Pull requests stay small and aim for at most three commits.\n- AI assistants are tools, not co-authors: do not add `Co-Authored-By`\n  trailers for them.\n- Use Python 3.12+ idioms and TypeScript strict mode; keep comments for the\n  non-obvious \"why\".\n\nIf you found a security issue, please follow [SECURITY.md](SECURITY.md)\ninstead of opening a public issue.\n\n## License\n\nMIT, see [`LICENSE`](LICENSE).\n\n## Contributors\n\nThanks goes to these people for code, translations, docs, design, and\nreview work on md-bridge ([emoji key](https://allcontributors.org/docs/en/emoji-key)):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"16.66%\"\u003e\u003ca href=\"https://github.com/vinicq\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/78210890?v=4?s=80\" width=\"80px;\" alt=\"Vinicius Queiroz\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eVinicius Queiroz\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=vinicq\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=vinicq\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#design-vinicq\" title=\"Design\"\u003e🎨\u003c/a\u003e \u003ca href=\"#infra-vinicq\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e \u003ca href=\"#maintenance-vinicq\" title=\"Maintenance\"\u003e🚧\u003c/a\u003e \u003ca href=\"https://github.com/vinicq/md-bridge/pulls?q=is%3Apr+reviewed-by%3Avinicq\" title=\"Reviewed Pull Requests\"\u003e👀\u003c/a\u003e \u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=vinicq\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"16.66%\"\u003e\u003ca href=\"https://github.com/zhouzhou626\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/255877794?v=4?s=80\" width=\"80px;\" alt=\"zhouzhou626\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ezhouzhou626\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=zhouzhou626\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=zhouzhou626\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#translation-zhouzhou626\" title=\"Translation\"\u003e🌍\u003c/a\u003e \u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=zhouzhou626\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"#a11y-zhouzhou626\" title=\"Accessibility\"\u003e️️️️♿️\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"16.66%\"\u003e\u003ca href=\"https://github.com/ko4lax\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/20627319?v=4?s=80\" width=\"80px;\" alt=\"koala\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ekoala\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=ko4lax\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=ko4lax\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=ko4lax\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"#translation-ko4lax\" title=\"Translation\"\u003e🌍\u003c/a\u003e \u003ca href=\"#a11y-ko4lax\" title=\"Accessibility\"\u003e️️️️♿️\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"16.66%\"\u003e\u003ca href=\"https://github.com/GiulianaCDA\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/56075340?v=4?s=80\" width=\"80px;\" alt=\"Giuliana Arecippo\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eGiuliana Arecippo\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=GiulianaCDA\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#design-GiulianaCDA\" title=\"Design\"\u003e🎨\u003c/a\u003e \u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=GiulianaCDA\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"16.66%\"\u003e\u003ca href=\"https://github.com/0exec\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/68334134?v=4?s=80\" width=\"80px;\" alt=\"0exec\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003e0exec\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=0exec\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=0exec\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=0exec\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"#infra-0exec\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"16.66%\"\u003e\u003ca href=\"https://github.com/alucard210319\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/7868450?v=4?s=80\" width=\"80px;\" alt=\"alucard210319\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ealucard210319\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=alucard210319\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#infra-alucard210319\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"16.66%\"\u003e\u003ca href=\"https://github.com/pink\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/7690638?v=4?s=80\" width=\"80px;\" alt=\"Sean Kallungal\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eSean Kallungal\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=pink\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"16.66%\"\u003e\u003ca href=\"https://github.com/lvupupui\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/276037412?v=4?s=80\" width=\"80px;\" alt=\"lvupupui\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003elvupupui\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=lvupupui\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=lvupupui\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"#translation-lvupupui\" title=\"Translation\"\u003e🌍\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"16.66%\"\u003e\u003ca href=\"https://github.com/homesellerq-coder\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/294912019?v=4?s=80\" width=\"80px;\" alt=\"Home Seller\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eHome Seller\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=homesellerq-coder\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=homesellerq-coder\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"https://github.com/vinicq/md-bridge/commits?author=homesellerq-coder\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the\n[all-contributors](https://github.com/all-contributors/all-contributors)\nspecification. Contributions of every kind welcome.\n\n---\n\n## If md-bridge helped you\n\nA star ⭐ on GitHub is the single most useful thing you can do; it makes the\nproject discoverable for the next person looking for a self-hosted PDF\nconverter.\n\n### Star history\n\n\u003ca href=\"https://www.star-history.com/#vinicq/md-bridge\u0026Date\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/svg?repos=vinicq/md-bridge\u0026type=Date\u0026theme=dark\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/svg?repos=vinicq/md-bridge\u0026type=Date\"\u003e\n    \u003cimg alt=\"Star history chart for vinicq/md-bridge\" src=\"https://api.star-history.com/svg?repos=vinicq/md-bridge\u0026type=Date\"\u003e\n  \u003c/picture\u003e\n\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvinicq%2Fmd-bridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvinicq%2Fmd-bridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvinicq%2Fmd-bridge/lists"}