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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
844 changes: 714 additions & 130 deletions .pages.yml

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ docker run --rm -v "$(pwd):/app" -w /app node:22 npm install <package>

## Pages CMS

[`.pages.yml`](.pages.yml) configures browser editing for `docs/pages/` and images in `docs/public/img/`. See [CONTRIBUTING.md](CONTRIBUTING.md) for app installation, editor invitations, and trusted-editor access and direct publishing to `main`. Keep its category choices aligned with existing frontmatter tags. Preserve the plain-text body editor: VitePress spoilers, includes, and components require lossless Markdown. Metadata extraction uses YAML parsing to support CMS list serialization.
[`.pages.yml`](.pages.yml) configures browser editing for `docs/pages/` and images in `docs/public/img/`. See [CONTRIBUTING.md](CONTRIBUTING.md) for app installation, editor invitations, and trusted-editor access and direct publishing to `main`. Keep its category choices aligned with existing frontmatter tags. The body uses rich-text Markdown with an Editor/Source switch. Use Source mode for VitePress spoilers, includes, HTML and components and preserve their Markdown syntax. Metadata extraction uses YAML parsing to support CMS list serialization.

## Adding or editing pages

All wiki pages live in [`docs/pages/`](docs/pages/). Each is a standard Markdown file with YAML frontmatter:
All wiki pages live in topic/alphabetic leaf folders under [`docs/pages/`](docs/pages/). Each topic has a Pages CMS group with one collection per leaf folder. Use the appropriate topic and filename range when creating a page; the public URL stays `/wiki/pages/<Filename>` regardless of its source folder. Each is a standard Markdown file with YAML frontmatter:

```yaml
---
Expand Down Expand Up @@ -68,7 +68,7 @@ Use relative Markdown links with the `.md` extension:
[Back to classes](../classes.md)
```

Do **not** use wikilink syntax `[text](Page "wikilink")` — the migration script converts those but the VitePress site uses standard links.
Do **not** use wikilink syntax `[text](Page "wikilink")` — the VitePress site uses standard Markdown links.

## Adding images

Expand Down Expand Up @@ -128,7 +128,7 @@ Open a pull request — GitHub Actions will build your changes. Once a maintaine
This file (`AGENTS.md`) is read automatically by Claude Code, OpenAI Codex, Gemini CLI, and other agents that support the `AGENTS.md` convention. Keep it up to date so agents have accurate project context.

Key facts for agents:
- All wiki content is in `docs/pages/*.md` — edit there, not in `_pages/` (legacy source)
- All wiki content is in `docs/pages/**/*.md` — edit there, not in `_pages/` (legacy source)
- Images live in `docs/public/img/` and are referenced as `/img/filename`
- Dev server: `docker compose up dev` (port 5174)
- Build command: `docker compose up --build wiki` (port 4173); or `npm run docs:build` inside the container
Expand Down
10 changes: 7 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Secret information here...

A maintainer must connect the repository first (see below). Editors can sign in with GitHub or accept a Pages CMS email invitation from a maintainer. If you do not have editor access, use the GitHub pull request route below.

Trusted members edit directly on **`main`**. Accept your invitation, open the wiki repository in Pages CMS, select `main`, and choose **Wiki pages** to edit an existing page or create one. Use **Images** to upload pictures. Check your content and spoilers before saving.
Trusted members edit directly on **`main`**. Accept your invitation, open the wiki repository in Pages CMS, select `main`, and choose the **topic → alphabetic collection** for the article to edit an existing page or create one. Use **Images** to upload pictures. Check your content and spoilers before saving.

**Saving commits your changes directly to `main` and triggers the site build and deployment.** Your edit appears on the live wiki after deployment succeeds; there is no branch preparation, pull request, or per-edit maintainer approval. If saving is denied or the site does not update after deployment, contact a maintainer. See the [browser editing guide](https://docs.mume.org/wiki/pages/Contributing) for detailed steps.

Expand All @@ -62,11 +62,15 @@ Local development requires [Docker](https://www.docker.com/).
2. Sign in at [Pages CMS](https://app.pagescms.org/) and install its GitHub App for this repository, following the [official quick start](https://pagescms.org/docs/quick-start/). Organization installation may require an owner.
3. Configure GitHub branch protection/rulesets so the Pages CMS GitHub App can commit directly to `main`. If pull requests or pre-merge checks are required, grant the installed app an appropriate bypass for direct publishing. Keep the normal review requirements for other contributors. `.pages.yml` does not grant access or change GitHub branch rules.
4. Open this repository on `main` in Pages CMS and invite trusted members through its collaborator interface. [Email collaborators](https://pagescms.org/docs/configuration/collaborators/) do not need GitHub accounts or repository write access: their edits use the installed GitHub App's access. Invitations grant direct publishing access, so invite only members trusted to follow the wiki rules. A GitHub login alone does not grant editing access.
5. Verify onboarding with a trusted editor: accept the invitation, open the repository on `main`, save a small valid edit, and confirm that the **Deploy to GitHub Pages** workflow succeeds and the live wiki updates. No PR is needed. Test aliases, images, spoilers, and includes before wider rollout.
5. Verify onboarding with a trusted editor: accept the invitation, open the repository on `main`, save a small valid edit, and confirm that the **Deploy to GitHub Pages** workflow succeeds and the live wiki updates. No PR is needed. Test aliases, images, spoilers, and includes before inviting more editors.
6. Use GitHub history to inspect changes and revert mistakes, and remove the CMS collaborator invitation when someone should no longer publish. If that person also has GitHub repository access, manage that separately.

The existing deployment workflow runs on pushes to `main`. A saved edit remains in Git history even if validation or deployment fails; fix or revert the offending change and let deployment run again. Editors can ask a maintainer for help with failed builds or rollbacks.

The schema edits only `docs/pages/` and uploads images to `docs/public/img/`, writing `/img/…` URLs. Page bodies use plain text to preserve VitePress containers, includes, HTML, and Vue components; a visual rich-text round trip has not been validated for these constructs. Unknown frontmatter keys are preserved with `settings.content.merge`.
The schema edits only `docs/pages/` and uploads images to `docs/public/img/`, writing `/img/…` URLs. Page bodies offer WYSIWYG editing with Markdown output and an Editor/Source switch. Use Source mode for spoilers, includes, HTML, script examples, and Vue components. Inspect the source before saving. Unknown frontmatter keys are preserved with `settings.content.merge`.

Page renaming and deletion are disabled in the CMS to avoid breaking links. New filenames must use the wiki convention (e.g. `Grey_Havens.md`); replace the suggested filename if needed, and omit leading `A`, `An`, or `The`. Section indexes and shared includes remain maintained through GitHub. When introducing a category, update the category choices in `.pages.yml` alongside the content.

## Topic collections

Articles are organized by topic and alphabetic filename range. Choose the topic first, then the collection for the article’s filename. Each article has one source file; tags can place it in multiple categories. Moving a source file between collections does not change its public `/wiki/pages/<Filename>` URL. Keep filenames unchanged when editing existing pages.
63 changes: 51 additions & 12 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
import { defineConfig } from 'vitepress'
import fs from 'fs'
import path from 'path'
import { slugify } from './shared'
import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)
const { getMarkdownFiles } = require('../../scripts/utils.cjs')
const { publicRoute, topicFor, topicRoute } = require('../../scripts/routes.cjs')
const sources = getMarkdownFiles(path.resolve(__dirname, '../pages')).map((file: string) => path.relative(path.resolve(__dirname, '..'), file).replace(/\\/g, '/'))
const names = new Set<string>()
for (const source of sources) {
const name = path.basename(source)
if (names.has(name)) throw new Error('Duplicate article filename: ' + name)
names.add(name)
}
const preview = (process.env.VITEPRESS_BASE ?? '/wiki/').includes('/pr-') || process.env.WIKI_PREVIEW === 'true'

let pagesMeta = { terms: {}, paths: [], tags: {} }
try {
pagesMeta = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../public/pages-meta.json'), 'utf-8'))
} catch (e) {}
const sortedTerms = Object.keys(pagesMeta.terms || {}).sort((a, b) => b.length - a.length)
const validPaths = new Set(pagesMeta.paths || [])
const termsByUrl = new Map<string, string[]>()
for (const [term, url] of Object.entries(pagesMeta.terms || {})) {
const terms = termsByUrl.get(url as string) || []
terms.push(term)
termsByUrl.set(url as string, terms)
}

const editRepo = process.env.EDIT_REPO || 'MUME/wiki'
const editBranch = process.env.EDIT_BRANCH || 'main'
Expand Down Expand Up @@ -49,12 +65,22 @@ export default defineConfig({
description: 'A community wiki and guide to surviving in Multi-Users in Middle-earth.',
base: process.env.VITEPRESS_BASE ?? '/wiki/',
cleanUrls: true,
lastUpdated: true,
sitemap: {
hostname: 'https://docs.mume.org/wiki/'
rewrites: (source) => source.startsWith('pages/') ? publicRoute(source).slice(1) + '.md' : source,
transformPageData(pageData) {
const source = pageData.filePath || pageData.relativePath
if (source.startsWith('pages/')) {
const topic = topicFor(pageData.frontmatter.tags || [])
pageData.frontmatter.wikiTopic = topic
pageData.frontmatter.wikiTopicRoute = topicRoute(topic)
}
pageData.frontmatter.head ??= []
if (!preview) pageData.frontmatter.head.push(['link', { rel: 'canonical', href: 'https://docs.mume.org/wiki' + publicRoute(source) }])
},
lastUpdated: true,
sitemap: preview ? undefined : { hostname: 'https://docs.mume.org/wiki/' },

head: [
...(preview ? [['meta', { name: 'robots', content: 'noindex, nofollow' }]] as any : []),
['link', { rel: 'icon', type: 'image/png', href: '/img/Main_Gandalf.png' }],
['meta', { name: 'theme-color', content: '#1a1410' }],
],
Expand All @@ -71,6 +97,8 @@ export default defineConfig({
{ text: 'Races', link: '/races' },
{ text: 'More',
items: [
{ text: 'All topics', link: '/topics' },
{ text: 'Software', link: '/topics/software' },
{ text: 'Lore', link: '/lore' },
{ text: 'History', link: '/history' },
{ text: 'Tags', link: '/tags' },
Expand Down Expand Up @@ -230,14 +258,26 @@ export default defineConfig({

markdown: {
config(md) {
// Relative links retain the original flat published context after a source move.
md.core.ruler.after('inline', 'canonical-links', (state) => {
if (!state.env.relativePath?.startsWith('pages/')) return
for (const token of state.tokens) for (const child of token.children || []) {
if (child.type !== 'link_open') continue
const href = child.attrGet('href')
if (href && !/^(?:[a-z]+:|\/|#)/i.test(href)) {
const [target, suffix = ''] = href.split(/(?=[#?])/s, 2)
child.attrSet('href', '/' + path.posix.normalize('pages/' + target) + suffix)
}
}
})
// 1. Core auto-linking for text
md.core.ruler.after('inline', 'auto-link', (state) => {
if (state.env.frontmatter?.autolink === false) {
return;
}

const currentUrl = state.env.relativePath
? '/' + state.env.relativePath.replace(/\.md$/, '').replace(/\\/g, '/')
? publicRoute(state.env.relativePath)
: '';
const usedTerms = new Set();

Expand All @@ -252,14 +292,12 @@ export default defineConfig({
if (href.startsWith('/')) {
absoluteHref = href.replace(/\.md$/, '');
} else {
const dir = path.dirname(state.env.relativePath || '');
const dir = path.posix.dirname(publicRoute(state.env.relativePath || '').slice(1));
absoluteHref = '/' + path.join(dir, href).replace(/\.md$/, '').replace(/\\/g, '/');
if (absoluteHref === '/.') absoluteHref = '/';
}
for (const [term, url] of Object.entries(pagesMeta.terms || {})) {
if (url === absoluteHref || url === absoluteHref.replace('/pages/', '/')) {
usedTerms.add(term);
}
for (const url of [absoluteHref, absoluteHref.replace('/pages/', '/')]) {
for (const term of termsByUrl.get(url) || []) usedTerms.add(term);
}
}
}
Expand All @@ -282,6 +320,7 @@ export default defineConfig({
if (isInLink) continue;

const text = child.content;
const lowerText = text.toLowerCase();
let bestMatch = null;
let bestIndex = -1;

Expand All @@ -290,7 +329,7 @@ export default defineConfig({
const targetUrl = pagesMeta.terms[term];
if (targetUrl === currentUrl || targetUrl === currentUrl.replace('/pages/', '/')) continue;

const index = text.toLowerCase().indexOf(term);
const index = lowerText.indexOf(term);
if (index !== -1) {
const before = index > 0 ? text[index - 1] : ' ';
const after = index + term.length < text.length ? text[index + term.length] : ' ';
Expand Down
5 changes: 5 additions & 0 deletions docs/.vitepress/theme/Layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ const { frontmatter } = useData()
<template>
<Layout>
<template #doc-before>
<nav v-if="frontmatter.wikiTopic" aria-label="Breadcrumb" class="wiki-breadcrumb">
<a :href="withBase('/')">Wiki</a> →
<a :href="withBase(frontmatter.wikiTopicRoute)">{{ frontmatter.wikiTopic }}</a> →
<span>{{ frontmatter.title }}</span>
</nav>
<StubNotice />
<div v-if="frontmatter.hero && frontmatter.hero.image" class="hero-image-fix">
<!-- Injected to ensure local images are used -->
Expand Down
14 changes: 9 additions & 5 deletions docs/.vitepress/theme/NotFound.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
This page does not exist yet.
</p>

<label>New page collection
<select v-model="newCollection"><option v-for="folder in meta.collections" :key="folder" :value="folder">{{ folder.replace('pages/', '') }}</option></select>
</label>
<div class="not-found-actions">
<a :href="withBase('/pages/Contributing')" class="action-btn secondary">
Contribute with Pages CMS
Expand All @@ -30,7 +33,7 @@
</a>
<a
v-else
:href="`https://github.com/${editRepo}/new/${editBranch}/docs/pages`"
:href="`https://github.com/${editRepo}/new/${editBranch}/docs/${newCollection}`"
target="_blank"
rel="noopener"
class="action-btn secondary"
Expand All @@ -55,10 +58,12 @@
</template>

<script setup lang="ts">
import meta from '../../public/pages-meta.json'
import { onMounted, ref, computed } from 'vue'
import { inBrowser, useData, withBase } from 'vitepress'

const { site } = useData()
const newCollection = ref(meta.collections.find(folder => folder.startsWith('pages/Reference/')) || meta.collections[0])
const pageName = ref('')
const rawSlug = ref('')

Expand All @@ -70,17 +75,16 @@ const createUrl = computed(() => {
const filename = rawSlug.value.replace(/\s+/g, '_') + '.md'
const stub = [
'---',
`title: ${rawSlug.value}`,
`title: ${JSON.stringify(rawSlug.value)}`,
'description: ',
'tags:',
' - ',
'tags: []',
'---',
'',
`# ${rawSlug.value}`,
'',
'<!-- Add content here -->',
].join('\n')
return `https://github.com/${editRepo}/new/${editBranch}/docs/pages?filename=${encodeURIComponent(filename)}&value=${encodeURIComponent(stub)}`
return `https://github.com/${editRepo}/new/${editBranch}/docs/${newCollection.value}?filename=${encodeURIComponent(filename)}&value=${encodeURIComponent(stub)}`
})

function goBack() {
Expand Down
10 changes: 10 additions & 0 deletions docs/.vitepress/theme/components/TopicArticles.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script setup>
import { withBase } from 'vitepress'
import meta from '../../../public/pages-meta.json'
defineProps({ topic: String })
</script>
<template>
<section><h2 :id="'topic-articles'">All articles</h2>
<ul><li v-for="article in meta.topics[topic]" :key="article.url"><a :href="withBase(article.url)">{{ article.title }}</a></li></ul>
</section>
</template>
2 changes: 2 additions & 0 deletions docs/.vitepress/theme/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import DefaultTheme from 'vitepress/theme'
import Layout from './Layout.vue'
import NotFound from './NotFound.vue'
import ImageMap from './components/ImageMap.vue'
import TopicArticles from './components/TopicArticles.vue'
import StubNotice from './components/StubNotice.vue'
import CookieConsent from './components/CookieConsent.vue'
import './style.css'
Expand All @@ -16,6 +17,7 @@ export default {
app.component('ImageMap', ImageMap)
app.component('NotFound', NotFound)
app.component('StubNotice', StubNotice)
app.component('TopicArticles', TopicArticles)
app.component('CookieConsent', CookieConsent)

// Handle 404 redirection from public/404.html shim
Expand Down
2 changes: 2 additions & 0 deletions docs/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,5 @@ If you're looking for a specific playstyle, these community-written guides are e
<hr />

<ClassRace />

<TopicArticles topic="Classes" />
2 changes: 2 additions & 0 deletions docs/equipment.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,5 @@ Full identified stats and mechanics: [**Weapon List**](./pages/Weapon.md)
- [**Condition**](./pages/Whetstone.md) — Keeping your weapons sharp and gear repaired.
- [**Enchanting**](./pages/Enchant.md) — Improving your equipment via magic.
- [**Equipment Terminology**](./pages/Other_equipment.md) — Explanation of flags like Magic, Nosell, Eff vs.

<TopicArticles topic="Equipment" />
2 changes: 2 additions & 0 deletions docs/guides.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,5 @@ Deep dives into specific playstyles and builds:
## Help improve the wiki

[Contributing](./pages/Contributing.md) explains how to edit with Pages CMS or GitHub and follow the content and spoiler rules.

<TopicArticles topic="Guides" />
2 changes: 2 additions & 0 deletions docs/lore.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,5 @@ Navigating the vast wilderness of Middle-earth is a skill in itself.

### Browse More
[Full Locations Index](./tags.md)

<TopicArticles topic="Lore" />
Empty file added docs/pages/Classes/A-Z/.gitkeep
Empty file.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ Example:

[Back to skill list](./Skill.md)

<!--@include: ../includes/Skills.md-->
<!--@include: ../../../includes/Skills.md-->
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ The quality of the bandage will influence the healing speed.
The conditions of the bandage will deteriorate with time, so it is a
good idea to replace old bandages from time to time.

<!--@include: ../includes/Skills.md-->
<!--@include: ../../../includes/Skills.md-->
File renamed without changes.
2 changes: 1 addition & 1 deletion docs/pages/Bash.md → docs/pages/Commands/A-G/Bash.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ tags:

See also: [Kick](./Kick.md), [Rescue](./Rescue.md)

<!--@include: ../includes/Skills.md-->
<!--@include: ../../../includes/Skills.md-->
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ NOTE: This skill is considered useless.
- [Charging weapon](./Charging_weapon.md) for a list of weapons belonging to this class.
- [Newbie Guide to Warrior Skills](./Newbie_Guide_to_Warrior_Skills.md#charge)

<!--@include: ../includes/Skills.md-->
<!--@include: ../../../includes/Skills.md-->
2 changes: 1 addition & 1 deletion docs/pages/Climb.md → docs/pages/Commands/A-G/Climb.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,4 @@ current skill and hit points.

- [Swim](./Swim.md)

<!--@include: ../includes/Skills.md-->
<!--@include: ../../../includes/Skills.md-->
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion docs/pages/Info.md → docs/pages/Commands/H-Q/Info.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ see also: [Score](./Score.md), Stat,

---

<!--@include: ../includes/Guides.md-->
<!--@include: ../../../includes/Guides.md-->
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion docs/pages/Levels.md → docs/pages/Commands/H-Q/Levels.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ Typing `levels` shows a table of XP thresholds, helping you gauge how far you ar
- [Experience](./Experience.md) — How experience points are earned.
- [Hero](./Hero.md) — The tier unlocked at level 21.

<!--@include: ../includes/Guides.md-->
<!--@include: ../../../includes/Guides.md-->
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion docs/pages/Pick.md → docs/pages/Commands/H-Q/Pick.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ Examples:
> pick hiddensafe
```

<!--@include: ../includes/Skills.md-->
<!--@include: ../../../includes/Skills.md-->
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading
Loading