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
159 changes: 157 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && 'main-release' || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
validate:
Expand Down Expand Up @@ -114,3 +114,158 @@ jobs:

- name: Run web compatibility contract
run: mise run test:web:stable

release:
name: Release
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs:
- validate
- desktop-host
- web-host
runs-on: ubuntu-latest
timeout-minutes: 20
outputs:
released: ${{ steps.semantic-release.outputs.released }}
version: ${{ steps.semantic-release.outputs.version }}
git_tag: ${{ steps.semantic-release.outputs.git_tag }}
vsix_path: ${{ steps.semantic-release.outputs.vsix_path }}
checksum_path: ${{ steps.semantic-release.outputs.checksum_path }}
steps:
- name: Check out complete release history
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false

- name: Install locked tools
uses: jdx/mise-action@3c2e0cf82a5b2e5249f0d3635a4d83d0ae861518 # v4.2.5
with:
install: true
version: '2026.8.4'

- name: Install locked dependencies
run: mise run setup

- name: Create release bot token
id: release-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ vars.RELEASE_BOT_CLIENT_ID }}
private-key: ${{ secrets.RELEASE_BOT_PRIVATE_KEY }}
permission-contents: write
permission-issues: write

- name: Run Semantic Release
id: semantic-release
env:
GITHUB_TOKEN: ${{ steps.release-token.outputs.token }}
run: mise run release

- name: Upload immutable release package
if: steps.semantic-release.outputs.released == 'true'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: release-${{ steps.semantic-release.outputs.version }}
path: artifacts/
if-no-files-found: error
retention-days: 7

publish-vscode:
name: Publish to Visual Studio Marketplace
if: needs.release.outputs.released == 'true'
needs: release
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Install locked tools
uses: jdx/mise-action@3c2e0cf82a5b2e5249f0d3635a4d83d0ae861518 # v4.2.5
with:
install: true
version: '2026.8.4'

- name: Install locked dependencies
run: mise run setup

- name: Download immutable release package
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: release-${{ needs.release.outputs.version }}
path: artifacts

- name: Verify and publish VSIX
env:
VERSION: ${{ needs.release.outputs.version }}
VSCE_PAT: ${{ secrets.VSCE_PAT }}
VSIX_PATH: ${{ needs.release.outputs.vsix_path }}
run: | # zizmor: ignore[use-trusted-publishing] PAT publishing
(cd artifacts && sha256sum --check "jimeh.better-markdown-preview-${VERSION}.vsix.sha256")
pnpm exec vsce publish --packagePath "$VSIX_PATH"

publish-openvsx:
name: Publish to Open VSX
if: needs.release.outputs.released == 'true'
needs: release
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Install locked tools
uses: jdx/mise-action@3c2e0cf82a5b2e5249f0d3635a4d83d0ae861518 # v4.2.5
with:
install: true
version: '2026.8.4'

- name: Install locked dependencies
run: mise run setup

- name: Download immutable release package
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: release-${{ needs.release.outputs.version }}
path: artifacts

- name: Verify and publish VSIX
env:
OVSX_PAT: ${{ secrets.OVSX_PAT }}
VERSION: ${{ needs.release.outputs.version }}
VSIX_PATH: ${{ needs.release.outputs.vsix_path }}
run: | # zizmor: ignore[use-trusted-publishing] PAT publishing
(cd artifacts && sha256sum --check "jimeh.better-markdown-preview-${VERSION}.vsix.sha256")
pnpm exec ovsx publish "$VSIX_PATH"

upload-github-release:
name: Attach GitHub Release assets
if: needs.release.outputs.released == 'true'
needs: release
permissions:
contents: write
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Download immutable release package
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: release-${{ needs.release.outputs.version }}
path: artifacts

- name: Verify and attach release assets
env:
CHECKSUM_PATH: ${{ needs.release.outputs.checksum_path }}
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
GIT_TAG: ${{ needs.release.outputs.git_tag }}
VERSION: ${{ needs.release.outputs.version }}
VSIX_PATH: ${{ needs.release.outputs.vsix_path }}
run: |
(cd artifacts && sha256sum --check "jimeh.better-markdown-preview-${VERSION}.vsix.sha256")
gh release view "$GIT_TAG"
gh release upload "$GIT_TAG" "$VSIX_PATH" "$CHECKSUM_PATH" --clobber
69 changes: 69 additions & 0 deletions .github/workflows/semantic-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: semantic-pr

on: # zizmor: ignore[dangerous-triggers] metadata-only PR title check
# No checkout or untrusted code execution.
pull_request_target:
types:
- opened
- edited
- reopened
- synchronize

permissions:
pull-requests: write

concurrency:
group: semantic-pr-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
validate-title:
name: Validate PR title
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- id: lint_pr_title
uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
build
chore
ci
docs
feat
fix
perf
refactor
revert
style
test
subjectPattern: ^(?![A-Z]).+$
subjectPatternError: The subject must not start with an uppercase character.

- name: Comment on invalid PR title
if: ${{ !cancelled() && steps.lint_pr_title.outputs.error_message != null }}
uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5
with:
header: pr-title-lint-error
message: |
Hey there and thank you for opening this pull request!

We require pull request titles to follow the
[Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/)
and it looks like your proposed title needs to be adjusted.

Details:

```
${{ steps.lint_pr_title.outputs.error_message }}
```

- name: Remove PR title lint comment
if: ${{ steps.lint_pr_title.outputs.error_message == null }}
continue-on-error: true
uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5
with:
header: pr-title-lint-error
delete: true
Comment thread
coderabbitai[bot] marked this conversation as resolved.
1 change: 1 addition & 0 deletions .vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ mise.lock
mise.toml
pnpm-lock.yaml
pnpm-workspace.yaml
release.config.mjs
vsc-extension-quickstart.md
**/tsconfig.json
**/tsconfig.*.json
Expand Down
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ VSCE accepts only `ui` and `workspace` in `extensionKind`. Web-host eligibility
comes from the manifest's `browser` entry point; do not add a synthetic `web`
extension kind.

`@semantic-release/release-notes-generator` 14.1.1 is compatible with
`conventional-changelog-conventionalcommits` 9.3.1. Version 10 uses a newer
writer contract and silently produced release headings without commit entries;
retain the executable release-notes contract when upgrading either package.

VSCE's positional package version calls `npm version` unless both
`--no-git-tag-version` and `--no-update-package-json` are supplied. Release
packaging must keep those flags because Semantic Release has already modified
the transient changelog and the tracked manifest must stay at `0.0.0`.

GitHub Actions must declare restricted permissions and pin every action to a
full commit SHA. `mise run ci:workflows` enforces syntax, security posture, and
pin freshness.
24 changes: 2 additions & 22 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,4 @@
# Changelog

All notable changes to Better Markdown Preview will be documented here.

## [Unreleased]

- Scaffold the behavior-free desktop and web extension foundation.
- Add the repository validation, test, packaging, and CI harness.
- Enhance the built-in Markdown preview with GFM, alerts, footnotes, definition
lists, TOML frontmatter, responsive columns, and local Mermaid diagrams.
- Add a theme-aware document layout, responsive table of contents, and rich
native-highlighted code-fence presentation.
- Support the desktop Extension Host and a browser-compatible web bundle with
focused parser, DOM lifecycle, Extension Host, and packaged-artifact
validation.
- Add default-on settings for each optional rendering feature, the table of
contents, smooth navigation, and the Mermaid zoom and pan viewer.
- Animate table-of-contents navigation while respecting reduced-motion
preferences, and soften the Mermaid viewer backdrop.
- Compact list indentation, align task checkboxes with ordinary list markers,
remove the rectangular ToC focus treatment, and match the mobile ToC backdrop
to the Mermaid viewer.
- Render TOML and YAML frontmatter as expanded, collapsible,
syntax-highlighted code without delimiter lines.
Release history is available in
[GitHub Releases](https://github.com/jimeh/vscode-better-markdown-preview/releases).
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,13 @@ are:
- `mise run test:web:stable` exercises stable VS Code for the Web in Chromium
after `mise run test:hosts:prepare`.
- `mise run package:validate` builds and inspects the VSIX.
- `mise run release:check` exercises versioning, notes, outputs, and workflow
contracts without publishing.
- `mise run verify` runs the intended-final-head local gate.

See [Architecture](docs/architecture.md) and [Testing](docs/testing.md) for the
contracts those commands enforce.
contracts those commands enforce. See [Releases](docs/releases.md) for the
automated versioning, publication, and recovery contract.

## License

Expand Down
27 changes: 23 additions & 4 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,26 @@ explicit ESM `.mts` files. Node 24 executes these files through native type
stripping, while `tsconfig.tooling.json` independently applies strict NodeNext,
no-emit checking and restricts the files to erasable TypeScript syntax.

`.vscode-test.mjs` is the sole JavaScript compatibility exception because
`@vscode/test-cli` 0.0.15 discovers `.json`, `.js`, `.cjs`, and `.mjs` configs
but not `.mts`. Reusable version and invocation logic remains in checked `.mts`
helpers rather than the compatibility file.
JavaScript compatibility files are kept as thin discovery shims when an
external tool cannot discover `.mts`. `@vscode/test-cli` 0.0.15 discovers
`.vscode-test.mjs`, while Semantic Release discovers `release.config.mjs`.
Reusable host and release policy remains in strictly checked `.mts` helpers
rather than either compatibility file.

## Release Boundary

The tracked extension version is the development placeholder `0.0.0`.
Semantic Release owns version selection from squash commit messages and passes
the selected version to the repository's VSCE packaging helper; it does not
edit or commit the manifest. Release preparation runs after all source and host
gates, injects the version only into the VSIX, checks the complete archive and
transient current-release changelog, and produces a SHA-256 file.

Visual Studio Marketplace, Open VSX, and GitHub Release publication are
independent consumers of that one immutable artifact. Publisher jobs never
rebuild it and receive only their own credential. GitHub Releases are the
cumulative changelog authority; see [Releases](releases.md) for operational
policy and recovery.

## Public Contracts

Expand All @@ -128,3 +144,6 @@ and shipped artifacts describe the current implementation.

The rendering contract is recorded in
`docs/plans/002-renderer-implementation.md`.

The automated release contract is recorded in
`docs/plans/004-semantic-release-automation.md`.
Loading