diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..52da550 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,129 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces — the issue tracker, +discussions, pull requests, and commit history — and also applies when an +individual is officially representing the community in public spaces. Examples +of representing our community include using an official email address, posting +via an official social media account, or acting as an appointed representative +at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the maintainer at **leonardo.salas01@outlook.com**. All complaints +will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +https://www.contributor-covenant.org/version/2/1/code_of_conduct.html. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][mozilla]. + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. + +[homepage]: https://www.contributor-covenant.org +[mozilla]: https://github.com/mozilla/inclusion diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..a13599e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,186 @@ +# Contributing to doc-engine-cli + +Contributions are welcome from anyone — bug reports, documentation fixes, new +templates, and features are all useful. This guide covers what you need to know +to get a change merged. + +By participating, you agree to follow the [Code of Conduct](CODE_OF_CONDUCT.md). + +--- + +## Ways to contribute + +| I want to... | Go here | +|---|---| +| Report a bug | [Open an issue](https://github.com/leonardosalasd/doc-engine-cli/issues/new) | +| Ask a question | [Discussions → Q&A](https://github.com/leonardosalasd/doc-engine-cli/discussions/categories/q-a) | +| Suggest a feature | [Discussions → Ideas](https://github.com/leonardosalasd/doc-engine-cli/discussions/categories/ideas) | +| Report a security issue | [Security policy](SECURITY.md) — please do not open a public issue | +| Fix something yourself | Read on | + +--- + +## Getting set up + +```bash +git clone https://github.com/leonardosalasd/doc-engine-cli.git +cd doc-engine-cli +python -m venv .venv +source .venv/bin/activate # Windows: .venv\Scripts\activate +pip install -e ".[dev]" +``` + +Check that the tool runs before changing anything: + +```bash +doc-engine info +python -m pytest tests/ -v +``` + +--- + +## Testing + +Run the suite before opening a pull request: + +```bash +python -m pytest tests/ -v +``` + +**Test on more than one Python version.** This matters more than it sounds: +`v1.1.0` shipped completely broken on Python 3.10 through 3.13 because it was +only ever run on 3.14, where deferred annotation evaluation hid an import-time +crash. CI now covers 3.10–3.14 on Linux, macOS, and Windows, but catching it +locally is faster. If you have [uv](https://github.com/astral-sh/uv): + +```bash +uv run --python 3.10 --no-project --with mistune --with click --with rich \ + --with typst --with pytest python -m pytest tests/ -q +``` + +Swap `3.10` for any version in the supported range. + +New behavior needs a test. Bug fixes need a test that fails before the fix and +passes after it — that is what stops the same bug from coming back. + +--- + +## Code style + +There is no autoformatter in this project. Match the surrounding code: + +- Type hints on function signatures. +- Module-level constants in `SCREAMING_SNAKE_CASE`, prefixed with `_` when private. +- Helper functions prefixed with `_`. +- Tests grouped in classes named `TestSomething`, one behavior per method. +- Docstrings where the *why* is not obvious from the code. Skip them where it is. +- No decorative comment banners (`# ====`, `# ----`). If a comment is needed, + write a sentence explaining the reasoning, not a divider. + +Keep changes focused. A pull request that fixes one thing is easier to review, +and far easier to revert if it turns out to be wrong. + +--- + +## Commit messages + +The history uses [Conventional Commits](https://www.conventionalcommits.org/): + +``` +feat: add support for A4 page size +fix: prevent crash on legacy Windows consoles +docs: document the --watch flag +ci: test on Python 3.14 +chore: bump version to 1.1.1 +``` + +Write the subject in the imperative mood, under ~72 characters. If the change +needs explanation, put it in the body: what was broken, why the fix works, and +anything a future reader would need in order to not undo it by accident. + +--- + +## Pull requests + +1. Branch from `main` using a descriptive prefix: `feat/`, `fix/`, or `docs/`. +2. Make your change, with tests. +3. Run the suite and confirm it passes. +4. Open the pull request against `main`. + +Every pull request is reviewed by the repository owner +([CODEOWNERS](.github/CODEOWNERS)), and CI must be green before merging. CI runs +the test suite across every supported Python version and operating system, plus +a smoke job that installs the built package and drives the CLI from a clean +directory. + +In the description, explain what changed and why. If it fixes an open issue, +reference it with `Fixes #123`. + +--- + +## Adding a template + +Templates live in [`doc_engine/templates/`](doc_engine/templates) as `.typ` +files. Each one exposes a single `setup_doc` entry point, and the compiler +passes it the document metadata: + +```typ +#let setup_doc( + title: "", + subtitle: "", + author: "Anonymous", + date: datetime.today().display(), + bibliography_file: none, + accent: none, + branding: true, + version: "", + body, +) = { ... } +``` + +The quickest start is to copy an existing template and edit it. A new template +should: + +- Honor `accent` when it is not `none`, and fall back to its own default color. +- Honor `branding: false` by hiding the `doc-engine` attribution. +- Render `subtitle` only when it is not empty. +- Render the bibliography when `bibliography_file` is not `none`. + +Templates are discovered automatically, so dropping the file in is enough for +`--template ` to find it. Add it to the templates table in the README and +to the test in `tests/test_cli.py` that asserts the shipped set. + +--- + +## Project layout + +| Module | Responsibility | +|---|---| +| `cli.py` | Argument parsing, Git detection, watch loop, output naming | +| `frontmatter.py` | Leading `---` metadata block | +| `linter.py` | Source checks reported with line and column | +| `converter.py` | Markdown AST → Typst markup | +| `compiler.py` | Template injection and PDF compilation | + +Changes usually belong in exactly one of these. If a change needs to touch all +of them, it is worth opening a discussion first to agree on the approach. + +--- + +## Reporting bugs + +A good report includes: + +- What you ran and what happened, with the full error output. +- Your OS, Python version, and `doc-engine --version`. +- A minimal Markdown file that reproduces it, if the problem is in a document. + +The report that led to `v1.1.1` was excellent precisely because it pasted the +entire traceback — that made the diagnosis immediate. + +--- + +## License + +By contributing, you agree that your contributions are licensed under the +[MIT License](LICENSE) that covers this project. diff --git a/README.md b/README.md index b5eb67e..99b09fe 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![PyPI](https://img.shields.io/pypi/v/doc-engine-cli.svg?logo=pypi&logoColor=white&color=006DAD)](https://pypi.org/project/doc-engine-cli/) [![PyPI Downloads](https://static.pepy.tech/personalized-badge/doc-engine-cli?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/doc-engine-cli) [![Typst](https://img.shields.io/badge/Powered_by-Typst-239DAD.svg?logo=typst&logoColor=white)](https://typst.app/) -[![Code style: black](https://img.shields.io/badge/code_style-black-000000.svg)](https://github.com/psf/black) +[![Tests](https://github.com/leonardosalasd/doc-engine-cli/actions/workflows/tests.yml/badge.svg)](https://github.com/leonardosalasd/doc-engine-cli/actions/workflows/tests.yml) Transform any `README.md` into a premium, print-ready PDF report — no configuration, no templates, no LaTeX. @@ -507,13 +507,19 @@ docker run --rm -v "$PWD:/workspace" ghcr.io/leonardosalasd/doc-engine-cli build ## Contributing -Contributions are welcome. Please follow these guidelines: +Contributions are welcome — bug reports, documentation fixes, new templates, and +features. The [contributing guide](CONTRIBUTING.md) covers setup, testing across +Python versions, code style, and how to add a template. -1. Fork the repository -2. Create a feature branch (`git checkout -b feature/your-feature`) -3. Write tests for new functionality -4. Ensure all tests pass (`python -m pytest tests/ -v`) -5. Submit a pull request +| | | +|---|---| +| [Contributing guide](CONTRIBUTING.md) | Setup, tests, style, pull requests | +| [Code of conduct](CODE_OF_CONDUCT.md) | Expected behavior in community spaces | +| [Security policy](SECURITY.md) | Reporting a vulnerability privately | +| [Support](SUPPORT.md) | Where to ask questions and report problems | + +Questions belong in [Discussions](https://github.com/leonardosalasd/doc-engine-cli/discussions/categories/q-a); +bugs belong in [Issues](https://github.com/leonardosalasd/doc-engine-cli/issues). --- diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..273783a --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,97 @@ +# Security Policy + +## Supported versions + +Security fixes are applied to the latest release. If you are on an older +version, upgrade before reporting: + +```bash +pipx upgrade doc-engine-cli +``` + +| Version | Supported | +|---|---| +| 1.1.x | Yes | +| 1.0.x | Please upgrade | +| < 1.0 | No | + +--- + +## Reporting a vulnerability + +**Please do not open a public issue, discussion, or pull request for a security +problem.** Public reports expose users who have not upgraded yet. + +Report it privately, in either of these ways: + +1. **GitHub Security Advisories (preferred)** — use the + [Security tab](https://github.com/leonardosalasd/doc-engine-cli/security) + and choose *Report a vulnerability*. This opens a private advisory that only + you and the maintainer can see, and it keeps the whole discussion, the fix, + and the disclosure in one place. + +2. **Email** — write to **leonardo.salas01@outlook.com**. + +Sending both is welcome: the advisory keeps the technical thread organized, and +the email makes sure it is seen quickly. + +### What to include + +- The version of `doc-engine-cli` and your Python version and OS. +- What an attacker can achieve, and what access they would need to do it. +- Steps to reproduce, ideally with a minimal Markdown file, template, or + command. Please describe the payload rather than attaching anything harmful. +- Any suggested fix, if you have one in mind. + +### What to expect + +- **Acknowledgement within 72 hours.** If you have not heard back by then, + please send a follow-up — it means the message did not reach me. +- An assessment of whether the report is accepted, along with the reasoning. +- Progress updates while a fix is being prepared. +- A release with the fix, and a published advisory once users have had a + reasonable chance to upgrade. + +Please give me a chance to ship a fix before disclosing publicly. If you plan to +publish on a particular date, say so in your first message and we will work +toward it. + +--- + +## Credit + +If you report a valid vulnerability, you will be credited in the +[GitHub Security Advisory](https://docs.github.com/en/code-security/security-advisories/working-with-repository-security-advisories/editing-a-repository-security-advisory#about-credits-for-security-advisories) +for the fix, which also credits you on the published CVE record when one is +issued. Tell me the name or handle you would like to be credited as, or let me +know if you would rather stay anonymous. + +There is no paid bug bounty for this project. + +--- + +## Scope + +This is a command-line tool that reads Markdown and templates from your machine +and produces a PDF. Reports are most relevant when they involve: + +- Reading or writing files outside the intended input and output paths, for + example through a crafted image path, bibliography path, or template path. +- Arbitrary code or command execution triggered by a Markdown file, a `.typ` + template, or front-matter values. +- Crafted input that causes the compiler to hang indefinitely or exhaust memory. + +Out of scope: + +- Vulnerabilities in dependencies — report those upstream to + [`typst`](https://github.com/messense/typst-py), + [`mistune`](https://github.com/lepture/mistune), + [`click`](https://github.com/pallets/click), or + [`rich`](https://github.com/Textualize/rich). If a dependency issue affects + this project specifically, a report here is still useful. +- Crashes and malformed output that carry no security impact. Those are ordinary + bugs — please [open an issue](https://github.com/leonardosalasd/doc-engine-cli/issues/new). + +A `.typ` template is executable input by design: pointing `--template` at a file +means running it. Treat templates from untrusted sources the same way you would +treat any other code you download and run. diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000..4d6865f --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,58 @@ +# Getting Help + +This project is maintained by one person in his spare time. Using the right +channel makes it much more likely your question gets a useful answer quickly. + +--- + +## Where to go + +| Your situation | Where | +|---|---| +| "How do I do X?" | [Discussions → Q&A](https://github.com/leonardosalasd/doc-engine-cli/discussions/categories/q-a) | +| "Something is broken" | [Issues](https://github.com/leonardosalasd/doc-engine-cli/issues) | +| "It would be great if it could..." | [Discussions → Ideas](https://github.com/leonardosalasd/doc-engine-cli/discussions/categories/ideas) | +| "I built something with it" | [Discussions → Show and tell](https://github.com/leonardosalasd/doc-engine-cli/discussions/categories/show-and-tell) | +| "I found a security problem" | [Security policy](SECURITY.md) — please report privately | +| "I want to contribute code" | [Contributing guide](CONTRIBUTING.md) | + +The distinction that matters most: **questions go to Discussions, defects go to +Issues.** If you are not sure which one it is, open a discussion — it is easy to +convert it into an issue once we know a bug is involved. + +--- + +## Before asking + +Most questions are already answered: + +- The [README](README.md) documents every command and flag, all five templates, + front matter, watch mode, and custom templates. +- `doc-engine --help` and `doc-engine build --help` list every option. +- `doc-engine build --dry-run` checks a Markdown file for problems and reports + them with the exact line and column. + +--- + +## Writing a good question + +Include enough for someone to reproduce what you are seeing: + +- The exact command you ran. +- What you expected, and what happened instead. +- The full output or error message — the complete text, not a screenshot of a + fragment. +- Your OS, your Python version, and the output of `doc-engine --version`. +- A minimal Markdown file that shows the problem, if the issue is with a + particular document. + +--- + +## Response times + +There is no service level agreement here. Expect a reply within a few days; +security reports are handled first, then bugs that break normal usage, then +everything else. + +If a thread goes quiet, a polite follow-up is fine — things fall through the +cracks sometimes.