Skip to content

chore: convert repo to pnpm monorepo (packages/desktop, muyajs, website) - #4302

Merged
Jocs merged 4 commits into
developfrom
chore/monorepo-split
May 29, 2026
Merged

Jocs merged 4 commits into
developfrom
chore/monorepo-split

Conversation

@Jocs

@Jocs Jocs commented May 29, 2026

Copy link
Copy Markdown
Member

Summary

Converts marktext into a pnpm workspace. The desktop Electron app moves into packages/desktop/, the existing src/muya/ becomes packages/muyajs/ (reserving the packages/muya/ slot for the future TS rewrite from https://github.com/marktext/muya), and the standalone marktext-website is imported as packages/website/.

Final layout:

packages/
├── desktop/   # Electron app (name: "marktext")
├── muyajs/    # Legacy markdown engine (name: "@marktext/muyajs", private)
└── website/   # marktext.app site (Vite + React, name: "marktext-website")

CI is unchanged

This was the hard constraint of the refactor. No .github/workflows/* file is touched. All five workflows (build / test / lint / e2e / validate-licenses) keep invoking pnpm <script> from the repo root:

  • Root package.json keeps every CI-facing script name and proxies via pnpm --filter marktext <script>
  • electron-builder.yml adds directories.output: ../../dist so installers land in the repo-root dist/ (where upload-artifact path: dist/* looks for them)
  • scripts/postinstall.ts etc. internally target packages/desktop/ so workspace-local binaries (electron, patch-package, electron-rebuild) are found
  • scripts/thirdPartyChecker.ts reads workspace package names+versions at runtime, so version bumps don't need a manual exclusion update

Commits

  1. chore(monorepo): introduce pnpm workspace and extract muya as packages/muyajs — workspace skeleton + muya → packages/muyajs (paths only, no code changes)
  2. chore(monorepo): move Electron desktop app into packages/desktop — relocates the desktop app, splits package.json, updates scripts/ to be desktop-aware, tightens eslint ignores, adds license-check exclusions
  3. chore(monorepo): import marktext-website as packages/website — snapshot copy of the standalone site (history not preserved per the agreed plan)
  4. docs(claude): reflect monorepo layout in CLAUDE.md — Tech Stack, Directory Structure, Workflow, Testing, Architecture, and Path Aliases sections rewritten

Test plan

Verified locally (all green on macOS arm64):

  • pnpm install --frozen-lockfile --ignore-scripts (CI step 1)
  • pnpm tsx scripts/postinstall.ts (Electron download / patch-package / electron-rebuild / minify-locales all succeed)
  • pnpm lint — 0 errors / 77 warnings (matches develop)
  • pnpm typecheck
  • pnpm test — 9 files / 550 tests pass
  • pnpm validate-licenses
  • pnpm build:unpack
  • pnpm build:mac:arm64 — produces signed DMG + zip at repo-root dist/, matching the CI artifact glob
  • pnpm dev — Electron app launches; editor / preferences / themes / locales all load
  • pnpm --filter marktext-website dev / build — Vite dev server + static build

CI to watch on this PR: build.yml (5 platforms), test.yml, lint.yml, e2e.yml, validate-licenses.yml.

🤖 Generated with Claude Code

Jocs and others added 4 commits May 29, 2026 10:10
…s/muyajs

Add `packages/*` to pnpm-workspace.yaml and relocate src/muya into
packages/muyajs (name: @marktext/muyajs, private). Aliases in
electron.vite.config.ts, vitest.config.ts and tsconfig.base.json now
point at packages/muyajs, and the eslint scopes that targeted src/muya
have been updated to match. Consumer import paths ('muya/lib/...') are
unchanged.

This lays the ground for a future packages/muya holding muya-v2 from
https://github.com/marktext/muya without colliding with the current
engine.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Relocate the desktop app (src/, electron.vite.config.ts, electron-builder.yml,
tsconfig*, vitest.config.ts, build/, static/, test/, patches/) into
packages/desktop. The root package.json is now a workspace orchestrator that
proxies every CI-facing script through `pnpm --filter marktext ...`, so the
existing CI workflows continue to invoke `pnpm <script>` from the repo root
without any working-directory changes. electron-builder writes its artifacts
to ../../dist via directories.output, keeping the upload-artifact globs
pointed at `dist/*` valid.

Workspace-shared tooling (ESLint, Prettier, tsx, license-checker) stays at
the root; all Electron/Vue/build-time deps move into the desktop package.
@marktext/muyajs is added as a workspace:* dependency, and the muya alias in
electron.vite/vitest/tsconfig now resolves to ../muyajs.

scripts/postinstall.ts, minify-locales.ts, generateThirdPartyLicense.ts and
validateLicenses.ts now operate against packages/desktop (its node_modules,
patches/, static/locales/ and build/) since workspace-local deps are not
hoisted to the root. minify-locales drops a dead fs.existsSync probe — let
readdirSync surface its own ENOENT.

packages/muyajs/package.json gains the runtime deps muya imports from npm
(github-markdown-css, katex, dompurify, snabbdom, …) so Node module
resolution stays inside the workspace instead of escaping into the parent
directory's node_modules.

ESLint: widen out/dist ignores to **/out/** and **/dist/** (the new
package-local output dirs), disable the deprecated core no-extra-semi
(defer to @stylistic/no-extra-semi from neostandard, which understands
leading-semi standard guards), and update the muya/desktop globs.

License check: derive the workspace exclusion list from each package's
own package.json at runtime so version bumps stay in sync automatically.
@marktext/file-icons remains pinned because it's a published dep that
license-checker fails to detect (MIT).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Snapshot the marktext-website source from its standalone repo into
packages/website (src/, public/, build/, index.html, vite.config.ts,
tsconfig*, package.json, README.md, .gitignore). The website keeps its
existing name (marktext-website), its own React 18 / Vite 5 toolchain
and continues to depend on @muyajs/core from npm — local muya
consumption can be wired in a follow-up if needed.

History was not preserved (single import commit) per the agreed plan.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Update Tech Stack, Directory Structure, Development Workflow, Testing,
Architecture, and Important Build Notes sections to describe the new
packages/{desktop,muyajs,website} layout: where files moved, how the
root scripts proxy to packages/desktop via pnpm --filter, the updated
muya alias and workspace dep wiring, electron-builder's `../../dist`
output redirection, and the patches/ relocation.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Copilot AI review requested due to automatic review settings May 29, 2026 02:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@github-actions

Copy link
Copy Markdown

Build artifacts for PR #4302:

Run: https://github.com/marktext/marktext/actions/runs/26613901732

Artifact Size Link
marktext-linux 592.6 MB Download
marktext-windows-arm64 270.4 MB Download
marktext-windows-x64 271.7 MB Download
marktext-macos-x64 271.4 MB Download
marktext-macos-arm64 261.2 MB Download

@Jocs
Jocs merged commit 565bfcd into develop May 29, 2026
11 checks passed
@Jocs
Jocs deleted the chore/monorepo-split branch May 29, 2026 02:28
codeforhome added a commit to codeforhome/marktext that referenced this pull request Jun 3, 2026
Merges 37 upstream commits into the fork, including the pnpm monorepo
conversion (marktext#4302), muya TS rewrite migration (marktext#4314), website package,
and fixes through CJK emphasis boundary (marktext#4355).

Conflict resolutions:
- package.json: adopt upstream monorepo root shell; drop fork's
  root-level deps block; move 4 fork-added deps (diff, @types/diff,
  markdown-it, @types/markdown-it) to packages/desktop/package.json
- build.yml: keep both fork's workflow_dispatch+dynamic-matrix and
  upstream's paths-ignore: packages/muya/**
- wsl.ts, comparisonPane.vue, wsl-paths.spec.ts: accepted git's rename
  detection — files live under packages/desktop/ in the monorepo layout
- docs/dev/FORK_PLAN.md: kept at repo-root docs/dev/ (private fork doc,
  not published website content)
- pnpm-lock.yaml: regenerated via pnpm install
@Jocs Jocs mentioned this pull request Jun 4, 2026
2 of 4 tasks
Jocs added a commit that referenced this pull request Jun 4, 2026
Two regressions from the monorepo conversion (#4302, #4314) broke
`pnpm run build:mac/win/linux` outside CI:

- electron is only a devDependency of packages/desktop. With pnpm
  workspaces, `shamefully-hoist=true` does not surface it at the
  workspace root, so electron-vite's `require.resolve('electron/
  package.json')` (resolved from its own .pnpm location) fails. Pin
  electron at the workspace root so it is hoisted into root
  node_modules.

- packages/muyajs/lib/renderers/index.js dynamically imports
  flowchart.js, mermaid and vega-embed, but these were only declared
  in packages/desktop. Vite/Rollup can resolve them when bundling the
  renderer alone, but in a strict pnpm layout muyajs cannot see its
  sibling's deps. Declare them as muyajs's own dependencies so each
  package owns what it imports.

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
thimbleberrysystems pushed a commit to thimbleberrysystems/WordBird that referenced this pull request Jun 21, 2026
…te) (marktext#4302)

* chore(monorepo): introduce pnpm workspace and extract muya as packages/muyajs

Add `packages/*` to pnpm-workspace.yaml and relocate src/muya into
packages/muyajs (name: @marktext/muyajs, private). Aliases in
electron.vite.config.ts, vitest.config.ts and tsconfig.base.json now
point at packages/muyajs, and the eslint scopes that targeted src/muya
have been updated to match. Consumer import paths ('muya/lib/...') are
unchanged.

This lays the ground for a future packages/muya holding muya-v2 from
https://github.com/marktext/muya without colliding with the current
engine.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* chore(monorepo): move Electron desktop app into packages/desktop

Relocate the desktop app (src/, electron.vite.config.ts, electron-builder.yml,
tsconfig*, vitest.config.ts, build/, static/, test/, patches/) into
packages/desktop. The root package.json is now a workspace orchestrator that
proxies every CI-facing script through `pnpm --filter marktext ...`, so the
existing CI workflows continue to invoke `pnpm <script>` from the repo root
without any working-directory changes. electron-builder writes its artifacts
to ../../dist via directories.output, keeping the upload-artifact globs
pointed at `dist/*` valid.

Workspace-shared tooling (ESLint, Prettier, tsx, license-checker) stays at
the root; all Electron/Vue/build-time deps move into the desktop package.
@marktext/muyajs is added as a workspace:* dependency, and the muya alias in
electron.vite/vitest/tsconfig now resolves to ../muyajs.

scripts/postinstall.ts, minify-locales.ts, generateThirdPartyLicense.ts and
validateLicenses.ts now operate against packages/desktop (its node_modules,
patches/, static/locales/ and build/) since workspace-local deps are not
hoisted to the root. minify-locales drops a dead fs.existsSync probe — let
readdirSync surface its own ENOENT.

packages/muyajs/package.json gains the runtime deps muya imports from npm
(github-markdown-css, katex, dompurify, snabbdom, …) so Node module
resolution stays inside the workspace instead of escaping into the parent
directory's node_modules.

ESLint: widen out/dist ignores to **/out/** and **/dist/** (the new
package-local output dirs), disable the deprecated core no-extra-semi
(defer to @stylistic/no-extra-semi from neostandard, which understands
leading-semi standard guards), and update the muya/desktop globs.

License check: derive the workspace exclusion list from each package's
own package.json at runtime so version bumps stay in sync automatically.
@marktext/file-icons remains pinned because it's a published dep that
license-checker fails to detect (MIT).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* chore(monorepo): import marktext-website as packages/website

Snapshot the marktext-website source from its standalone repo into
packages/website (src/, public/, build/, index.html, vite.config.ts,
tsconfig*, package.json, README.md, .gitignore). The website keeps its
existing name (marktext-website), its own React 18 / Vite 5 toolchain
and continues to depend on @muyajs/core from npm — local muya
consumption can be wired in a follow-up if needed.

History was not preserved (single import commit) per the agreed plan.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* docs(claude): reflect monorepo layout in CLAUDE.md

Update Tech Stack, Directory Structure, Development Workflow, Testing,
Architecture, and Important Build Notes sections to describe the new
packages/{desktop,muyajs,website} layout: where files moved, how the
root scripts proxy to packages/desktop via pnpm --filter, the updated
muya alias and workspace dep wiring, electron-builder's `../../dist`
output redirection, and the patches/ relocation.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants