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
2 changes: 1 addition & 1 deletion docs/ember/ember-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ order: 3
## Prerequisites

- Classic Ember CLI application
- Node `^20.19.0 || >=22.12.0`
- Node `>=22.22.2`
- `@docfy/ember` for runtime components (covered in [Tutorial](./tutorial.md))

## Installation
Expand Down
14 changes: 10 additions & 4 deletions docs/ember/upgrade-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ remark 11, rehype 11). Docfy's own packages are now ES modules.

### Node version

Docfy now requires Node `^20.19.0 || >=22.12.0`. This is not negotiable: those
are the versions where `require()` of an ES module works, which is what allows
the classic Ember CLI build and CommonJS config files to keep working against
ESM-only packages.
Docfy now requires Node `>=22.22.2`. Note what that drops: Node 20 entirely, and
also Node 22.12 through 22.22. If you are on Node 20 or on an early 22.x, you need
to upgrade Node first.

Two different constraints combine to produce that floor. Docfy needs `require()` of
an ES module to work, which is what allows the classic Ember CLI build and CommonJS
config files to keep working against ESM-only packages; that support landed in Node
20.19 and 22.12, so on its own it would only require those. The floor is higher
because `hosted-git-info`, the dependency that builds "edit this page" links,
requires 22.22.2 as its own minimum.

### Your config file keeps working

Expand Down
16 changes: 12 additions & 4 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,18 @@ yarn init

## Requirements

Docfy is published as ES modules and requires Node `^20.19.0 || >=22.12.0`. Those
are the Node versions that support `require()` of ES modules, which is what lets
CommonJS tooling (Ember CLI, a CommonJS config file) load Docfy and ESM-only
remark/rehype plugins.
Docfy is published as ES modules and requires Node `>=22.22.2`.

Two separate constraints combine to produce that floor. Docfy needs `require()` of
an ES module to work, which is what lets CommonJS tooling (Ember CLI, a CommonJS
config file) load Docfy and ESM-only remark/rehype plugins; that support landed in
Node 20.19 and 22.12. The floor is higher than those versions because
`hosted-git-info`, the dependency Docfy uses to build "edit this page" links,
requires 22.22.2 as its own minimum.

That dependency expresses its range as a list of LTS lines, which excludes
odd-numbered releases such as Node 23 and 25. Docfy uses a plain `>=` instead, so
developing on a current release does not produce install warnings.

## Add `@docfy/core` as a dependency

Expand Down
5 changes: 2 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"fast-glob": "^3.3.3",
"git-repo-info": "^2.1.1",
"github-slugger": "^2.0.0",
"hosted-git-info": "^3.0.8",
"hosted-git-info": "^10.1.1",
"mdast-util-to-string": "^4.0.0",
"rehype-stringify": "^10.0.1",
"remark-extract-frontmatter": "^3.2.0",
Expand All @@ -45,7 +45,6 @@
"@eslint/js": "^9.32.0",
"@types/debug": "^4.1.12",
"@types/hast": "^3.0.4",
"@types/hosted-git-info": "^3.0.5",
"@types/mdast": "^4.0.4",
"@types/node": "^24.0.14",
"@types/unist": "^3.0.0",
Expand All @@ -64,7 +63,7 @@
"vitest": "^3.2.4"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
"node": ">=22.22.2"
},
"publishConfig": {
"access": "public"
Expand Down
29 changes: 29 additions & 0 deletions packages/core/src/-private/hosted-git-info.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Minimal typings for the `hosted-git-info` members Docfy actually uses.
*
* The package ships no types of its own, and DefinitelyTyped's
* `@types/hosted-git-info` stopped at 3.0.5 — it was never updated for v4+, so
* it is now four majors behind and wrong in ways that matter: it declares the
* `*template` members as strings when they have been functions since v4, and
* its `Hosts` union does not know about hosts the current version parses.
*
* Declaring only what `repo-info.ts` consumes keeps the contract honest and
* small. None of this leaks into Docfy's public API — `getRepoEditUrl` returns
* `string | null`.
*/
declare module 'hosted-git-info' {
class GitHost {
/**
* Short host name. The current version reports `github`, `gitlab`,
* `bitbucket`, `gist` or `sourcehut`.
*/
type: string;
domain: string;
user: string;
project: string;

static fromUrl(gitUrl: string, options?: Record<string, unknown>): GitHost | undefined;
}

export = GitHost;
}
24 changes: 14 additions & 10 deletions packages/core/src/-private/repo-info.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import path from 'path';
import getRepoInfo from 'git-repo-info';
import GitHost, { fromUrl } from 'hosted-git-info';
import GitHost from 'hosted-git-info';

// A whitelist, not a fallback: `getTreePath` only knows two URL shapes, Bitbucket's
// and the `/edit/` form GitHub and GitLab accept. Every other host hosted-git-info can
// parse (gist, sourcehut, anything a future release adds) would otherwise be handed a
// plausible looking but wrong URL, and no edit link beats a broken one.
const supportedHostTypes = ['github', 'gitlab', 'bitbucket'];

function getTreePath(repo: GitHost | undefined, branch: string, relative: string): string {
if (repo && repo.type === 'bitbucket') {
Expand All @@ -25,19 +31,17 @@ export function getRepoEditUrl(root: string, repoURL: string, branch = 'master')

try {
const gitRoot = getRepoInfo(root).root;
const repo = fromUrl(repoURL);
const repo = GitHost.fromUrl(repoURL);
const relative = path.relative(gitRoot, root);
const tree = getTreePath(repo, branch, relative);

// The host's own `edit`/`browse` helpers percent-encode the path, which would
// mangle the `{filepath}` placeholder Docfy substitutes later on, so the URL is
// assembled from the parsed host metadata instead.
result =
(repo &&
repo.browsetemplate &&
repo.browsetemplate
.replace('{domain}', repo.domain)
.replace('{user}', repo.user)
.replace('{project}', repo.project)
.replace('{/tree/committish}', tree)) ||
null;
repo && supportedHostTypes.includes(repo.type)
? `https://${repo.domain}/${repo.user}/${repo.project}${tree}`
: null;
} catch (err) {
console.error(err);
result = null;
Expand Down
2 changes: 1 addition & 1 deletion packages/ember-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
"webpack": "^5.100.2"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
"node": ">=22.22.2"
},
"publishConfig": {
"access": "public"
Expand Down
2 changes: 1 addition & 1 deletion packages/ember-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"vite": ">= 6.0.0"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
"node": ">=22.22.2"
},
"publishConfig": {
"access": "public"
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-with-prose/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"vitest": "^3.2.4"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
"node": ">=22.22.2"
},
"publishConfig": {
"access": "public"
Expand Down
28 changes: 10 additions & 18 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion test-app-vite/app/templates/docs/ember/ember-cli.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { DocfyLink } from '@docfy/ember';
<h2 id="prerequisites"><a href="#prerequisites">Prerequisites</a></h2>
<ul>
<li>Classic Ember CLI application</li>
<li>Node <code>^20.19.0 || >=22.12.0</code></li>
<li>Node <code>>=22.22.2</code></li>
<li><code>@docfy/ember</code> for runtime components (covered in <DocfyLink @to="/docs/ember/tutorial" >Tutorial</DocfyLink>)</li>
</ul>
<h2 id="installation"><a href="#installation">Installation</a></h2>
Expand Down
13 changes: 9 additions & 4 deletions test-app-vite/app/templates/docs/ember/upgrade-guide.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@
<p>Version 0.13.0 moves Docfy onto the current unified/remark stack (unified 11,
remark 11, rehype 11). Docfy's own packages are now ES modules.</p>
<h3 id="node-version"><a href="#node-version">Node version</a></h3>
<p>Docfy now requires Node <code>^20.19.0 || >=22.12.0</code>. This is not negotiable: those
are the versions where <code>require()</code> of an ES module works, which is what allows
the classic Ember CLI build and CommonJS config files to keep working against
ESM-only packages.</p>
<p>Docfy now requires Node <code>>=22.22.2</code>. Note what that drops: Node 20 entirely, and
also Node 22.12 through 22.22. If you are on Node 20 or on an early 22.x, you need
to upgrade Node first.</p>
<p>Two different constraints combine to produce that floor. Docfy needs <code>require()</code> of
an ES module to work, which is what allows the classic Ember CLI build and CommonJS
config files to keep working against ESM-only packages; that support landed in Node
20.19 and 22.12, so on its own it would only require those. The floor is higher
because <code>hosted-git-info</code>, the dependency that builds "edit this page" links,
requires 22.22.2 as its own minimum.</p>
<h3 id="your-config-file-keeps-working"><a href="#your-config-file-keeps-working">Your config file keeps working</a></h3>
<p>There is no forced migration to <code>.mjs</code>. A CommonJS <code>.docfy-config.js</code> is still
fully supported, including <code>require()</code>-ing ESM-only remark/rehype plugins.
Expand Down
14 changes: 10 additions & 4 deletions test-app-vite/app/templates/docs/getting-started.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@ structures for your convenience.</p>
yarn init
</code></pre>
<h2 id="requirements"><a href="#requirements">Requirements</a></h2>
<p>Docfy is published as ES modules and requires Node <code>^20.19.0 || >=22.12.0</code>. Those
are the Node versions that support <code>require()</code> of ES modules, which is what lets
CommonJS tooling (Ember CLI, a CommonJS config file) load Docfy and ESM-only
remark/rehype plugins.</p>
<p>Docfy is published as ES modules and requires Node <code>>=22.22.2</code>.</p>
<p>Two separate constraints combine to produce that floor. Docfy needs <code>require()</code> of
an ES module to work, which is what lets CommonJS tooling (Ember CLI, a CommonJS
config file) load Docfy and ESM-only remark/rehype plugins; that support landed in
Node 20.19 and 22.12. The floor is higher than those versions because
<code>hosted-git-info</code>, the dependency Docfy uses to build "edit this page" links,
requires 22.22.2 as its own minimum.</p>
<p>That dependency expresses its range as a list of LTS lines, which excludes
odd-numbered releases such as Node 23 and 25. Docfy uses a plain <code>>=</code> instead, so
developing on a current release does not produce install warnings.</p>
<h2 id="add-docfycore-as-a-dependency"><a href="#add-docfycore-as-a-dependency">Add <code>@docfy/core</code> as a dependency</a></h2>
<pre><code class="hljs language-sh">npm install @docfy/core
<span class="hljs-comment"># or</span>
Expand Down
Loading