Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .charlie/instructions/pull-request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Charlie instructions for jsx-email (next/v3 branch)

Repo‑specific rules that keep Charlie aligned with this codebase and review preferences. Keep diffs small, mirror existing patterns, and don’t widen scope beyond the request.

## Scope
Applies to the entire repository, with extra focus on `packages/jsx-email` and its tests.

## Context
- Monorepo using pnpm + Moon. Most tasks are run with `pnpm moon run <project>:<task>`.
- Task inheritance lives in `.moon/tasks.yml`. Each project can add/override tasks in its own `moon.yml` (for example, `packages/jsx-email/moon.yml`). The root `moon.yml` defines repository tasks and is aliased as the `repo` project.
- TypeScript uses ESM with NodeNext resolution; relative imports in source include the `.js` suffix.
- Tests use Vitest; snapshots live in `.snapshots` next to tests (custom resolver).
- GitHub Actions sets `FORCE_COLOR=1` when running tests; local runs must mirror this to avoid ANSI snapshot diffs.
- Conventional Commits are the norm (e.g., `fix(jsx-email): …`). PRs should use the repository template.
- Conventional Commit scopes map to affected project name(s) under `packages/` (e.g., `(jsx-email)`, `(plugin-inline)`, `(create-jsx-email)`). When multiple projects are affected, list each name in the scope, comma‑separated with no spaces (e.g., `(plugin-inline,plugin-pretty)`). PRs should use the repository template.
- For the ongoing `next/v3` alignment work on `<Raw>` / `<Conditional>` behavior and core correctness (tracked in #348), branch from `origin/next/v3` and open pull requests with `base` set to `next/v3` (not `main`). Mention `#348` in the PR description for traceability.

## Rules
- [R1] Stay on task. Do not add refactors, helpers, or style tweaks outside the explicit ask. Keep diffs minimal.
- [R2] Tests and snapshots:
- Run with `FORCE_COLOR=1` to match CI.
- Never change log/ANSI‑colored snapshots to “de‑colorize” or “stabilize” output. If a log snapshot fails, fix the cause or mirror CI settings; do not rewrite the assertion shape.
- Do not introduce “snapshot normalization” helpers (e.g., projecting only parts of config objects) unless a maintainer requests it.
- Place/update snapshots under `.snapshots` alongside the test file; prefer targeted assertions plus snapshots when behavior changes intentionally.
- [R3] Writing tests for `packages/jsx-email`:
- Prefer importing from package source (e.g., `../src/index.ts`) for new tests to avoid prebuild coupling. If an existing suite imports from `dist`, keep that pattern for that suite.
- Avoid adding `// @ts-ignore` to suppress React imports; tests can rely on the React automatic JSX runtime. Don’t add new ignores.
- Follow NodeNext import style in source files (relative imports include `.js`).
- [R4] Verification commands (run locally before marking a PR Ready for changes that affect code, tests, or tooling config):
- Build artifacts used by tests:
- `pnpm moon run plugin-inline:build plugin-minify:build plugin-pretty:build`
- `pnpm moon run jsx-email:build`
- Lint: `pnpm moon run repo:lint`
- Tests (jsx-email package, mirroring the `next/v3` CI setup): `pnpm moon run jsx-email:test`
- TypeScript (package): `pnpm moon run jsx-email:tsc`
- Do not change tool configs or CI to make checks pass.
- For documentation-only or `.charlie`-only changes that do not affect CI, code, or tests, you may skip these commands, but prefer running at least `pnpm moon run repo:lint` when in doubt.
- [R4.1] Linting (must run before pushing any commits):
- Run repo linting via Moon: `pnpm moon run repo:lint`.
- Do not push if linting reports errors anywhere. Fix them or coordinate a follow‑up if they are unrelated but surfaced by your changes.
- If linting reports warnings in files you modified, resolve those warnings before pushing.
- For quick checks while iterating, you may run ESLint scoped to touched files, but always run the full `repo:lint` before the final push.
- [R5] Git & PRs:
- Branch names (from humans): `{type}/{project}/{short-desc}` — for example, `fix/jsx-email/conditional-endif-slash`. Use the package with the most changes (or the intended target) for `{project}`, and let `{short-desc}` be a descriptive phrase or a short slug.
- Conventional Commits scope = affected project name(s) from `packages/`. Examples: `fix(jsx-email): …`, `refactor(plugin-inline,plugin-pretty): …`. For multiple projects, list names comma-separated with no spaces.
- Commit messages use Conventional Commits; ≤ 72 chars in the subject; no emojis.
- PRs must use the repository template as-is — Charlie is not allowed to remove sections from the template.
- Start as Draft when work is in flux; mark Ready only after local verification passes and the description reflects the actual changes.
- Don’t add novel labels. Assign and request review from the human requester when appropriate.

> Conditional/Raw specifics have been moved to a dedicated playbook. See `.charlie/playbooks/conditional-and-raw.md`.

## References
1. CI workflow (test color): `.github/workflows/test-*.yml` (see `FORCE_COLOR=1` in test steps)
2. Vitest shared config: `shared/vitest.config.ts`
3. Moon tasks inheritance: `.moon/tasks.yml`; per-project tasks: `apps/*/moon.yml`, `packages/*/moon.yml`, `test/*/moon.yml`; repository tasks: `moon.yml` (project `repo`)
4. jsx-email package tasks: `packages/jsx-email/moon.yml`
5. Conventional Commits: https://www.conventionalcommits.org/en/v1.0.0/
6. Conditional/Raw playbook: `.charlie/playbooks/conditional-and-raw.md`
33 changes: 33 additions & 0 deletions .charlie/playbooks/conditional-and-raw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Conditional + Raw playbook (renderer and tests) — next/v3 branch

Apply this when changing how `<Conditional>` or `<Raw>` render (MSO/expr tokens, wrappers, or how nested Raw is inlined).

This copy lives on the `next/v3` branch. For the ongoing alignment work on `<Raw>` / `<Conditional>` semantics and tests (tracked in #348):
- Branch from `origin/next/v3`.
- Open pull requests with `base` set to `next/v3` (not `main`).
- Mention `#348` in the PR description so reviewers can tie the change back to the alignment effort.

Rules
- Include targeted tests and keep snapshot updates minimal (only intentional markup diffs).
- Do not introduce token “centralization” helpers or adjacency tests unless a maintainer explicitly requests them.
- Import from source for new tests to avoid prebuild coupling: `import { Conditional, Raw, render } from '../src/index.ts'`.

Test guidelines
- Closer/opener integrity
- Assert exactly one opener and closer for MSO: `<!--[if mso]>` and the current closer `<![endif]/-->`.
- Add a small case for the expression path (e.g., `expression="gte mso 16"`) and assert the same closer.
- No‑duplication when nesting Raw
- For `<Conditional mso><Raw …/></Conditional>`, assert the inner payload appears exactly once and not outside the block.
- Use `lastIndexOf` for closer slicing and allow opener at index `>= 0`.
- Snapshots and colorized logs
- Run with `FORCE_COLOR=1` to match CI. Never “de‑colorize” or normalize log snapshots.

Commands (jsx-email)
- Build artifacts some suites rely on: `pnpm moon run plugin-inline:build plugin-minify:build plugin-pretty:build && pnpm moon run jsx-email:build`
- Tests (CI‑aligned for `next/v3`): `pnpm moon run jsx-email:test` (the Moon task sets `FORCE_COLOR=1` like CI)
- TypeScript: `pnpm moon run jsx-email:tsc`

References
- CI workflow (color): `.github/workflows/test-*.yml` (look for `FORCE_COLOR=1`)
- Shared Vitest config: `shared/vitest.config.ts`
- Package tasks: `packages/jsx-email/moon.yml`
37 changes: 37 additions & 0 deletions .charlie/playbooks/run-jsx-email-tests-like-ci.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Run jsx-email tests locally exactly like CI (Moon + FORCE_COLOR) — next/v3 branch

## Overview
Run the `packages/jsx-email` test suite locally with the same settings the `next/v3` branch uses in CI so snapshots (including ANSI color) match exactly.

For the ongoing `next/v3` alignment work on `<Raw>` / `<Conditional>` behavior and core correctness (tracked in #348), branch from `origin/next/v3`, open PRs with `base` set to `next/v3` (not `main`), and mention `#348` in the PR description.

## Prerequisites
- Capabilities: GitHub + Devbox write access (local or CI).
- Tools: pnpm, Moon tasks (configured in this repo).
- Context: Some suites import from `dist/esm`, so plugin packages must be built first.

## Steps
1. Install deps and build required artifacts
- `pnpm install`
- `pnpm moon run plugin-inline:build plugin-minify:build plugin-pretty:build`
- `pnpm moon run jsx-email:build`
2. Run tests with color forced (matches CI)
- `pnpm moon run jsx-email:test` <!-- task sets FORCE_COLOR=1 in Moon config on next/v3 -->
3. Optional: update snapshots only for intentional HTML/markup changes (never for log/ANSI deltas)
- `cd packages/jsx-email && pnpm vitest -u --config ../../shared/vitest.config.ts && cd -`
4. TypeScript check (package)
- `pnpm moon run jsx-email:tsc`

## Verify
- Expect: `Test Files 44 passed`, `Tests 187 passed` (numbers may grow over time).
- No snapshot diffs for logs when `FORCE_COLOR=1` is set (the `jsx-email:test` Moon task configures this automatically).

## Rollback
- If you mistakenly updated snapshots for log/ANSI output, reset them:
- `git restore --source=origin/$(git rev-parse --abbrev-ref HEAD) -- "packages/jsx-email/test/**/.snapshots/*.snap" || true`
- Or discard all local changes: `git reset --hard`

## References
- CI workflow (color): `.github/workflows/test-*.yml` (look for `FORCE_COLOR=1`)
- Shared Vitest config: `shared/vitest.config.ts`
- Moon project tasks: `packages/jsx-email/moon.yml`
Loading