Stacks-Editor is a combination rich text / markdown editor that powers Stack Overflow's post editing experience.
Editor 1.x requires Stacks Classic 3 (@stackoverflow/stacks@^3.0.0)
and declares highlight.js@^11.6.0 as a peer dependency. Install them together:
npm install @stackoverflow/stacks-editor@^1.0.0 @stackoverflow/stacks@^3.0.0 highlight.js@^11.6.0Classic 2 and beta Classic releases are not supported by Editor 1.x. Applications
using Classic 2 should install Editor with the ^0.15.0 version range instead of
^1.0.0 or latest.
Editor intentionally depends on stable Stacks Icons V6. npm installs it automatically; a separate Icons installation or upgrade to V7 is not required.
<div id="editor-container"></div>import { StacksEditor } from "@stackoverflow/stacks-editor";
// don't forget to include the styles as well
import "@stackoverflow/stacks-editor/dist/styles.css";
// include the Classic styles as they're not included in the Editor styles
import "@stackoverflow/stacks/dist/css/stacks.css";
new StacksEditor(
document.querySelector("#editor-container"),
"*Your* **markdown** here"
);Load Classic CSS and Editor CSS separately. The Editor bundle includes the Stacks JavaScript it uses; load Classic JavaScript separately only if your page needs it for other Stacks components.
<!--include Stacks -->
<link rel="stylesheet" href="path/to/node_modules/@stackoverflow/stacks/dist/css/stacks.css" />
<!-- include the bundled styles -->
<link
rel="stylesheet"
href="path/to/node_modules/@stackoverflow/stacks-editor/dist/styles.css"
/>
<div id="editor-container"></div>
<!-- Optional: enables code-block syntax highlighting with Highlight.js 11 -->
<script src="https://unpkg.com/@highlightjs/cdn-assets@11/highlight.min.js"></script>
<!-- include the bundle -->
<script src="path/to/node_modules/@stackoverflow/stacks-editor/dist/app.bundle.js"></script>
<!-- initialize the editor -->
<script>
new window.stacksEditor.StacksEditor(
document.querySelector("#editor-container"),
"*Your* **markdown** here",
{}
);
</script>- Install dependencies with
npm i - Build and start using
npm start - Point your browser to the address listed in the output - typically http://localhost:8080/
Use the current Node LTS release. Install dependencies with npm ci and the
browser binaries with npx playwright install before running browser tests.
Run all unit tests (no end-to-end tests) using
npm run test:unit
Run all end-to-end tests (written in Playwright) using
npm run test:e2e
End-to-end tests need to follow the convention of using someName.e2e.test.ts as their filename. They'll automatically get picked up by the test runner this way.
Verify the published package and release configuration using:
npm run test:package
npm run test:release-configThe package check builds an npm tarball, installs it in a temporary consumer, type-checks the public imports, and bundles its JavaScript and CSS. It then opens the consumer in Chromium and checks editing and menu styling. Consumer installation may access npm; direct Classic, Icons, and Highlight.js versions match the repository lockfile. A missing Chromium binary fails the check.
Menu end-to-end tests cover keyboard operation and layout in light, dark,
high-contrast, and dark high-contrast themes across all three browsers.
They save heading-menu.png review artifacts in test-results/. These are
not pixel-regression baselines or a complete accessibility audit.
Generate a stats.json file for analysis using
npm run build:stats
You can upload your stats.json file here or here for visualization. See more resources here.
Documentation hostnames follow the Editor major version, not the Stacks Classic major version:
| Domain | Branch | Editor version | Classic compatibility |
|---|---|---|---|
editor.stackoverflow.design |
main |
1.x | Classic 3 |
v0.editor.stackoverflow.design |
v0 |
0.15.x | Classic 2 |
Netlify manages the build settings and the v0 branch subdomain. The v0 branch
supersedes the earlier v2 branch for legacy maintenance and documentation. Its
name reflects Editor's own major version; the old name referred to Classic 2.
The beta-host redirect is defined in netlify.toml. It redirects only
beta.editor.stackoverflow.design to the current host, preserving paths and
query parameters. It does not redirect the current site, legacy site, or deploy
previews.
To complete the beta-host cutover:
- Deploy the redirect configuration from
mainand verify the current andv0sites before changing domain assignments. - Remove
betafrom Netlify's branch subdomains, then addbeta.editor.stackoverflow.designas a production domain alias. The rules inmaindo not apply while that hostname still serves the separate beta branch. - Verify HTTPS and permanent redirects for the root and demo routes, including URLs with query parameters. Confirm that the destination editors still work.
- Remove
betaandv2from the branch-deploy allowlist, retainingv0. Branch-deploy settings are separate from Git branches; do not delete branches as part of this hosting change.
We use Changesets to publish to npm, create GitHub Releases, and update the changelog.
- Add a changeset to pull requests that require a package release.
- The release workflow creates and updates a release pull request against
mainwhile changesets are pending. - Merging the reviewed release pull request publishes the package under npm's
latesttag and creates a GitHub Release. - The
v0branch is configured for Editor 0.15.x maintenance releases under the separatelegacy-v0npm tag, without replacinglatestor creating GitHub Releases. That tag is created when a maintenance release is published; use an explicit0.15.xversion range until then.
The release job runs only after lint, unit, end-to-end, packed-package, and release-configuration tests pass.
Review the generated versions, dependency ranges, changelog, and package contents before merging the release pull request. Its merge authorizes publication; there is no additional manual approval step in the workflow.
When exiting prerelease mode, remove consumed changesets from both .changeset/
and .changeset/pre/. Changesets 3 reads the latter directory as release input,
so it must not be used to archive changesets from completed releases.
Continue using Conventional Commits for repository history.