Skip to content

Commit e928730

Browse files
committed
chore(website): version-aware docs URLs via remark plugin
Resolve version-sensitive docs URLs/versions at build time from each page's own path. Tokens: - {{yew_dependency}} -> `git = "..."` on next, `version = "X"` on snapshots - {{yew_api}} -> preview rustdoc host on next, docs.rs/yew/X on snapshots - {{yew_version}} -> latest release on next, X on snapshots (prose/display) Also fixes the 0.21-0.23 hooks links that wrongly pointed at the next preview host.
1 parent 40368e6 commit e928730

14 files changed

Lines changed: 239 additions & 11 deletions

File tree

website/docs/concepts/function-components/hooks/introduction.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Yew comes with the following predefined Hooks:
3939
- `use_context`
4040
- `use_force_update`
4141

42-
The documentation for these hooks can be found in the [Yew API docs](https://yew-rs-api.web.app/next/yew/functional/)
42+
The documentation for these hooks can be found in the [Yew API docs]({{yew_api}}functional/)
4343

4444
### Custom Hooks
4545

website/docs/getting-started/build-a-sample-app.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ version = "0.1.0"
6969
edition = "2021"
7070

7171
[dependencies]
72-
yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
72+
yew = { {{yew_dependency}}, features = ["csr"] }
7373
```
7474

7575
:::info

website/docusaurus.config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const { API_BUTTON } = require('./src/constants')
22
const rustDocHiddenLines = require('./src/remark/rustDocHiddenLines')
3+
const yewVersionUrls = require('./src/remark/yewVersionUrls')
34

45
const editUrl = 'https://github.com/yewstack/yew/blob/master/website/'
56

@@ -170,7 +171,7 @@ module.exports = {
170171
sidebarPath: require.resolve('./sidebars/docs.js'),
171172
editUrl,
172173
routeBasePath: '/docs',
173-
remarkPlugins: [rustDocHiddenLines],
174+
remarkPlugins: [rustDocHiddenLines, yewVersionUrls],
174175
},
175176
blog: {
176177
path: 'blog',
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Pure, dependency-free helpers for the `yewVersionUrls` remark plugin.
2+
//
3+
// Kept separate from the remark wrapper so the interesting logic (deriving the
4+
// documented version from a file path and expanding tokens) can be unit-tested
5+
// with plain `node`, without pulling in the unified/unist toolchain.
6+
7+
// The `next` docs document the unreleased API, so they get the git dependency
8+
// and the preview rustdoc host instead of a released version on docs.rs.
9+
const GIT_DEPENDENCY = 'git = "https://github.com/yewstack/yew/"'
10+
const PREVIEW_API_BASE = 'https://yew-rs-api.web.app/next/yew/'
11+
12+
/**
13+
* Determine what a docs source file documents, based on its path.
14+
*
15+
* - `website/docs/**` -> "next" (unreleased)
16+
* - `website/versioned_docs/version-X/**` -> X
17+
* - `website/i18n/<l>/...content-docs/current/**` -> "next"
18+
* - `website/i18n/<l>/...content-docs/version-X/**` -> X
19+
*
20+
* @param {string} filePath absolute or relative path to the .md(x) source
21+
* @param {string[]} versions contents of versions.json, newest first
22+
* @returns {{ version: string, isNext: boolean, display: string, dependency: string, api: string }}
23+
* - `display` : version string for prose (e.g. "0.23"; latest release on next)
24+
* - `dependency`: Cargo.toml specifier (`git = "…"` on next, else `version = "X"`)
25+
* - `api` : rustdoc base URL for the `yew` crate, ending in `/yew/`
26+
* (preview host on next, `docs.rs/yew/X/yew/` on snapshots)
27+
*/
28+
function versionContextFromPath(filePath, versions) {
29+
const latest = versions[0]
30+
const norm = String(filePath).replace(/\\/g, '/')
31+
// Matches both `versioned_docs/version-0.23/…` and the i18n equivalent
32+
// `…/docusaurus-plugin-content-docs/version-0.23/…`.
33+
const m = norm.match(/(?:^|\/)version-(\d+\.\d+(?:\.\d+)?)(?:\/|$)/)
34+
if (m) {
35+
const v = m[1]
36+
return {
37+
version: v,
38+
isNext: false,
39+
display: v,
40+
dependency: `version = "${v}"`,
41+
api: `https://docs.rs/yew/${v}/yew/`,
42+
}
43+
}
44+
// `docs/…` (next) or the i18n `…/current/…` mirror.
45+
return {
46+
version: latest,
47+
isNext: true,
48+
display: latest,
49+
dependency: GIT_DEPENDENCY,
50+
api: PREVIEW_API_BASE,
51+
}
52+
}
53+
54+
// Tokens authors write in the docs. Each resolves from the page's version ctx.
55+
const TOKENS = {
56+
// Cargo.toml: `yew = { {{yew_dependency}}, features = ["csr"] }`
57+
'{{yew_dependency}}': (ctx) => ctx.dependency,
58+
// Links: `[use_future]({{yew_api}}suspense/fn.use_future.html)`
59+
'{{yew_api}}': (ctx) => ctx.api,
60+
// Prose: `targets Yew {{yew_version}}`
61+
'{{yew_version}}': (ctx) => ctx.display,
62+
}
63+
64+
/** Replace every known yew token in `value` using `ctx`. */
65+
function applyTokens(value, ctx) {
66+
if (typeof value !== 'string' || value.indexOf('{{yew') === -1) return value
67+
let out = value
68+
for (const token of Object.keys(TOKENS)) {
69+
if (out.indexOf(token) !== -1) {
70+
out = out.split(token).join(TOKENS[token](ctx))
71+
}
72+
}
73+
return out
74+
}
75+
76+
module.exports = {
77+
versionContextFromPath,
78+
applyTokens,
79+
TOKENS,
80+
GIT_DEPENDENCY,
81+
PREVIEW_API_BASE,
82+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const { visit } = require('unist-util-visit')
2+
const { versionContextFromPath, applyTokens } = require('./yewVersionUrls.core')
3+
4+
// versions.json lives at the website root (../../ relative to src/remark).
5+
const versions = require('../../versions.json')
6+
7+
/**
8+
* Remark plugin: expand `{{yew_dependency}}`, `{{yew_api}}` and `{{yew_version}}`
9+
* placeholders to what the current docs page documents.
10+
*
11+
* `next` resolves to the git dependency and the preview rustdoc host (it documents
12+
* the unreleased API); a `version-X` snapshot resolves to `version = "X"` and
13+
* `docs.rs/yew/X`. Because each token is resolved from the page's own path at
14+
* build time, the snapshots created by `docusaurus docs:version` (and their
15+
* translations) keep resolving correctly with no manual edits — which is exactly
16+
* the maintenance burden this removes.
17+
*
18+
* Substitution is applied to text, inline code, fenced code blocks and link /
19+
* image URLs, so it works inside ```toml blocks (untouched by MDX interpolation)
20+
* as well as in prose links.
21+
*/
22+
function yewVersionUrls() {
23+
return (tree, file) => {
24+
const ctx = versionContextFromPath(
25+
file.path || (file.history && file.history[0]) || '',
26+
versions
27+
)
28+
29+
visit(tree, (node) => {
30+
if (typeof node.value === 'string') {
31+
node.value = applyTokens(node.value, ctx) // text, code, inlineCode
32+
}
33+
if (typeof node.url === 'string') {
34+
node.url = applyTokens(node.url, ctx) // link, image, definition
35+
}
36+
})
37+
}
38+
}
39+
40+
module.exports = yewVersionUrls
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Standalone unit test for the yew-version remark logic.
2+
// Run with: `node src/remark/yewVersionUrls.test.js` (no build / node_modules needed).
3+
const assert = require('assert')
4+
const { versionContextFromPath, applyTokens } = require('./yewVersionUrls.core')
5+
6+
const VERSIONS = ['0.23', '0.22', '0.21', '0.20']
7+
let passed = 0
8+
const check = (name, got, want) => {
9+
assert.deepStrictEqual(
10+
got,
11+
want,
12+
`${name}\n got: ${JSON.stringify(got)}\n want: ${JSON.stringify(want)}`
13+
)
14+
passed++
15+
}
16+
17+
const NEXT = {
18+
version: '0.23',
19+
isNext: true,
20+
display: '0.23',
21+
dependency: 'git = "https://github.com/yewstack/yew/"',
22+
api: 'https://yew-rs-api.web.app/next/yew/',
23+
}
24+
const V22 = {
25+
version: '0.22',
26+
isNext: false,
27+
display: '0.22',
28+
dependency: 'version = "0.22"',
29+
api: 'https://docs.rs/yew/0.22/yew/',
30+
}
31+
32+
// --- version derivation from path (next / snapshot / i18n) ---
33+
check(
34+
'next (docs/)',
35+
versionContextFromPath(
36+
'/repo/website/docs/getting-started/x.mdx',
37+
VERSIONS
38+
),
39+
NEXT
40+
)
41+
check(
42+
'versioned 0.22',
43+
versionContextFromPath(
44+
'/repo/website/versioned_docs/version-0.22/tutorial/index.mdx',
45+
VERSIONS
46+
),
47+
V22
48+
)
49+
check(
50+
'i18n next (current/)',
51+
versionContextFromPath(
52+
'/repo/website/i18n/ja/docusaurus-plugin-content-docs/current/x.mdx',
53+
VERSIONS
54+
),
55+
NEXT
56+
)
57+
check(
58+
'i18n versioned 0.22',
59+
versionContextFromPath(
60+
'/repo/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-0.22/x.mdx',
61+
VERSIONS
62+
),
63+
V22
64+
)
65+
66+
// --- token substitution: next uses git dep + preview host; snapshots use version + docs.rs ---
67+
const next = versionContextFromPath('/w/website/docs/x.mdx', VERSIONS)
68+
const v22 = versionContextFromPath(
69+
'/w/website/versioned_docs/version-0.22/x.mdx',
70+
VERSIONS
71+
)
72+
73+
check(
74+
'dependency (next -> git)',
75+
applyTokens('yew = { {{yew_dependency}}, features = ["csr"] }', next),
76+
'yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }'
77+
)
78+
check(
79+
'dependency (0.22 -> version)',
80+
applyTokens('yew = { {{yew_dependency}}, features = ["csr"] }', v22),
81+
'yew = { version = "0.22", features = ["csr"] }'
82+
)
83+
check(
84+
'api link (next -> preview host)',
85+
applyTokens('[use_future]({{yew_api}}suspense/fn.use_future.html)', next),
86+
'[use_future](https://yew-rs-api.web.app/next/yew/suspense/fn.use_future.html)'
87+
)
88+
check(
89+
'api link (0.22 -> docs.rs)',
90+
applyTokens('[use_future]({{yew_api}}suspense/fn.use_future.html)', v22),
91+
'[use_future](https://docs.rs/yew/0.22/yew/suspense/fn.use_future.html)'
92+
)
93+
check(
94+
'version token (next)',
95+
applyTokens('targets Yew {{yew_version}}', next),
96+
'targets Yew 0.23'
97+
)
98+
check(
99+
'version token (0.22)',
100+
applyTokens('targets Yew {{yew_version}}', v22),
101+
'targets Yew 0.22'
102+
)
103+
check('passthrough (no token)', applyTokens('plain text', next), 'plain text')
104+
105+
console.log(`ok — ${passed} assertions passed`)

website/versioned_docs/version-0.20/concepts/function-components/hooks/introduction.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Yew comes with the following predefined Hooks:
3838
- `use_context`
3939
- `use_force_update`
4040

41-
The documentation for these hooks can be found in the [Yew API docs](https://docs.rs/yew/0.20.0/yew/functional/index.html)
41+
The documentation for these hooks can be found in the [Yew API docs]({{yew_api}}functional/)
4242

4343
### Custom Hooks
4444

website/versioned_docs/version-0.20/getting-started/build-a-sample-app.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ version = "0.1.0"
6161
edition = "2021"
6262

6363
[dependencies]
64-
yew = { version = "0.20.0", features = ["csr"] }
64+
yew = { {{yew_dependency}}, features = ["csr"] }
6565
```
6666

6767
or using `cargo add yew -F csr`.

website/versioned_docs/version-0.21/concepts/function-components/hooks/introduction.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Yew comes with the following predefined Hooks:
3838
- `use_context`
3939
- `use_force_update`
4040

41-
The documentation for these hooks can be found in the [Yew API docs](https://yew-rs-api.web.app/next/yew/functional/)
41+
The documentation for these hooks can be found in the [Yew API docs]({{yew_api}}functional/)
4242

4343
### Custom Hooks
4444

website/versioned_docs/version-0.21/getting-started/build-a-sample-app.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ version = "0.1.0"
6969
edition = "2021"
7070

7171
[dependencies]
72-
yew = { version = "0.21", features = ["csr"] }
72+
yew = { {{yew_dependency}}, features = ["csr"] }
7373
```
7474

7575
or using `cargo add yew@0.21 -F csr`.

0 commit comments

Comments
 (0)