Remove guides, they moved to the minecraft wiki

This commit is contained in:
Misode
2023-11-23 01:35:58 +01:00
parent 27e5ea707b
commit 1394711d08
30 changed files with 143 additions and 1716 deletions

View File

@@ -25,10 +25,17 @@ export interface ConfigGenerator {
maxVersion?: string,
}
export interface ConfigLegacyGuide {
id: string,
title: string,
link: string,
}
export interface Config {
languages: ConfigLanguage[],
versions: ConfigVersion[],
generators: ConfigGenerator[],
legacyGuides: ConfigLegacyGuide[],
}
export default config as Config

View File

@@ -1,26 +0,0 @@
import { useMemo } from 'preact/hooks'
import { getGuide } from '../services/Guides.js'
import { Card } from './Card.jsx'
import { Badge } from './index.js'
interface Props {
id: string,
minimal?: boolean,
activeTags?: string[],
toggleTag?: (tag: string) => unknown,
}
export function GuideCard({ id, minimal, activeTags, toggleTag }: Props) {
const { title, versions, tags } = useMemo(() => getGuide(id), [id])
const onToggleTag = (tag: string) => (e: MouseEvent) => {
if (toggleTag) toggleTag(tag)
e.preventDefault()
e.stopImmediatePropagation()
}
return <Card title={title} overlay={!minimal && versions?.join(' • ')} link={`/guides/${id}/`}>
<div class="badges-list">
{tags?.sort().map(tag => <Badge label={tag} onClick={onToggleTag(tag)} active={activeTags?.includes(tag)} />)}
</div>
</Card>
}

View File

@@ -7,18 +7,17 @@ export * from './Card.jsx'
export * from './ErrorPanel.js'
export * from './FileUpload.js'
export * from './Footer.js'
export * from './forms/index.js'
export * from './generator/index.js'
export * from './Giscus.js'
export * from './GuideCard.jsx'
export * from './Header.js'
export * from './Icons.js'
export * from './Modal.js'
export * from './Octicon.js'
export * from './previews/index.js'
export * from './sounds/index.js'
export * from './ToolCard.js'
export * from './ToolGroup.jsx'
export * from './TreeView.js'
export * from './versions/index.js'
export * from './VersionSwitcher.js'
export * from './forms/index.js'
export * from './generator/index.js'
export * from './previews/index.js'
export * from './sounds/index.js'
export * from './versions/index.js'

View File

@@ -11,6 +11,6 @@ export function WhatsNewEntry({ item }: EntryProps) {
<WhatsNewTime item={item} />
<h2 class="font-bold text-[27px]">{item.title}</h2>
</a>
<div class="guide-content" dangerouslySetInnerHTML={{ __html: marked(item.body) }} />
<div class="markdown-content" dangerouslySetInnerHTML={{ __html: marked(item.body) }} />
</article>
}

View File

@@ -1,201 +1,24 @@
import hljs from 'highlight.js/lib/core'
import json from 'highlight.js/lib/languages/json'
import { marked } from 'marked'
import { route } from 'preact-router'
import { useCallback, useEffect, useMemo, useState } from 'preact/hooks'
import config from '../Config.js'
import { parseFrontMatter, versionContent } from '../Utils.js'
import { Ad, Badge, Btn, Footer, Giscus, Icons, Octicon, VersionSwitcher } from '../components/index.js'
import { useLocale, useTitle, useVersion } from '../contexts/index.js'
import { useActiveTimeout, useAsync, useHash } from '../hooks/index.js'
import type { VersionId } from '../services/index.js'
const HASH = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M6.368 1.01a.75.75 0 01.623.859L6.57 4.5h3.98l.46-2.868a.75.75 0 011.48.237L12.07 4.5h2.18a.75.75 0 010 1.5h-2.42l-.64 4h2.56a.75.75 0 010 1.5h-2.8l-.46 2.869a.75.75 0 01-1.48-.237l.42-2.632H5.45l-.46 2.869a.75.75 0 01-1.48-.237l.42-2.632H1.75a.75.75 0 010-1.5h2.42l.64-4H2.25a.75.75 0 010-1.5h2.8l.46-2.868a.75.75 0 01.858-.622zM9.67 10l.64-4H6.33l-.64 4h3.98z"></path></svg>'
hljs.registerLanguage('json', json)
marked.use({
highlight: (code, lang) => {
if (lang === '') return undefined
return hljs.highlight(code, { language: lang }).value
},
})
import { Footer } from '../components/Footer.jsx'
import { Octicon } from '../components/Octicon.jsx'
import { useTitle } from '../contexts/Title.jsx'
interface Props {
path?: string
id?: string
}
export function Guide({ id }: Props) {
const { locale } = useLocale()
const { version, changeVersion } = useVersion()
const { changeTitle } = useTitle()
const { value: content, refresh } = useAsync(async () => {
const res = await fetch(`../../guides/${id}.md`)
return await res.text()
}, [id])
if ((import.meta as any).hot) {
(import.meta as any).hot.on('guide-update', (updateId: string) => {
if (id === updateId) refresh()
})
}
const frontMatter = useMemo(() => {
if (!content) return undefined
const data = parseFrontMatter(content)
changeTitle(data?.title, data?.versions)
return data
}, [content])
const allowedVersions = useMemo(() => {
const orderedVersions = config.versions.map(v => v.id)
return (frontMatter?.versions as VersionId[])
?.sort((a, b) => orderedVersions.indexOf(b) - orderedVersions.indexOf(a))
}, [frontMatter?.versions])
const guideVersion = useMemo(() => {
if (!allowedVersions) return version
if (allowedVersions.includes(version)) return version
return allowedVersions[0]
}, [version, frontMatter?.versions])
const html = useMemo(() => {
if (!content) return undefined
const headings: marked.Tokens.Heading[] = []
let insertedToc = false
marked.use({
extensions: [
{
name: 'styledCode',
level: 'inline',
start(src) {
return src.match(/\b[fsnj]`/)?.index ?? -1
},
tokenizer(src) {
const match = src.match(/^([fsnj])`([^`]+)`/)
if (match) {
return {
type: 'styledCode',
raw: match[0],
prefix: match[1],
text: match[2],
}
}
return undefined
},
renderer(token) {
let content = token.text
let c = {
f: 'hljs-attr',
s: 'hljs-string',
n: 'hljs-number',
}[token.prefix as string]
if (token.prefix === 'j') {
content = hljs.highlight('json', token.text).value
c = 'language-json'
}
return `<code${c ? ` class="${c}"` : ''}>${content}</code>`
},
},
],
walkTokens(token) {
if (token.type === 'heading') {
headings.push(token)
}
},
renderer: {
link(href, title, text) {
if (href === null) return text
const title2 = title ? ` title="${title}"` : ''
const target = href?.match(/^https?:\/\//) ? ' target="_blank"' : ''
return `<a href="${href}"${title2}${target}>${text}</a>`
},
heading(text, level, raw, slugger) {
let toc = ''
if (!insertedToc) {
toc = `<ol class="guide-toc">${headings.filter(t => t.depth === 2).map(t => {
const id = slugger.slug(t.raw.match(/^#+ (.*)/)?.[1] ?? '', { dryrun: true })
const text = t.text.replaceAll('`', '')
return `<li><a href="#${id}">${text}</a></li>`
}).join('')}</ol>`
insertedToc = true
}
const id = slugger.slug(raw)
const link = `<span id="guide-${id}" href="?version=${version}#${id}">${HASH}</span>`
return `${toc}<h${level}>${link}${text}</h${level}>`
},
},
})
const guide = content.substring(content.indexOf('---', 3) + 3)
const versionedContent = versionContent(guide, guideVersion)
return marked(versionedContent, { version: '1.19' } as any)
}, [guideVersion, content])
const [hash, setHash] = useHash()
const scrollToHeading = useCallback(() => {
if (!html) return
const heading = document.querySelector(`[id=guide-${hash.slice(1)}]`)
if (heading) {
const top = heading.getBoundingClientRect().top + window.scrollY
window.scrollTo({ top: top - 68, behavior: 'smooth' })
}
}, [html, hash])
useEffect(() => {
scrollToHeading()
}, [html === undefined, hash])
const clickGuideContent = useCallback((e: MouseEvent) => {
if (!(e.target instanceof HTMLSpanElement)) return
const targetHash = '#' + e.target.id.replace(/^guide-/, '')
changeVersion(version, false, true)
setHash(targetHash)
if (targetHash === hash) {
scrollToHeading()
}
}, [scrollToHeading, hash, version])
const [shareActive, shareSuccess] = useActiveTimeout()
const onShare = useCallback(() => {
const url = `${location.origin}/guides/${id}/?version=${version}`
navigator.clipboard.writeText(url)
shareSuccess()
}, [id, version])
const onClickTag = useCallback((tag: string) => {
route(`/guides/?tags=${tag}`)
}, [])
const [largeWidth] = useState(window.innerWidth > 600)
const guide = config.legacyGuides.find(g => g.id === id)
useTitle(guide?.title)
return <main>
<div class="legacy-container guide">
<div class="navigation">
<a class="btn btn-link" href="/guides/">
{Octicon.arrow_left}
<span>{locale('guides.all')}</span>
</a>
{frontMatter?.tags?.includes('worldgen') && <a class="btn btn-link" href="/worldgen/">
{Icons.worldgen}
<span>{locale('worldgen')}</span>
</a>}
<div class="navigation-divider" />
<Btn icon={shareActive ? 'check' : 'link'} label={locale('share')} onClick={onShare} active={shareActive} tooltip={locale(shareActive ? 'copied' : 'copy_share')} class="guide-share" />
{allowedVersions && <VersionSwitcher value={guideVersion} allowed={allowedVersions} onChange={changeVersion} />}
</div>
{(frontMatter?.tags && frontMatter.tags.length > 0) && <div class="badges-list">
{frontMatter.tags.map((tag: string) =>
<Badge label={tag} active onClick={() => onClickTag(tag)} />
)}
</div>}
{html && <>
<Ad id="guide" type={largeWidth ? 'image' : 'text'} />
<div class="guide-content" dangerouslySetInnerHTML={{ __html: html }} onClick={clickGuideContent}></div>
<Giscus />
</>}
<div class="legacy-container">
<a class="tool-card minecraft-wiki" href={`https://minecraft.wiki/w/${guide?.link}`} target="_blank">
<img src="https://minecraft.wiki/images/Wiki@2x.png" alt="Minecraft Wiki Logo" />
<div>
<h3>This guide has moved to the <em>Minecraft Wiki</em> {Octicon.link_external}</h3>
</div>
</a>
</div>
<Footer />
</main>

View File

@@ -1,62 +1,25 @@
import { useMemo, useState } from 'preact/hooks'
import { Badge, Footer, GuideCard, TextInput, VersionSwitcher } from '../components/index.js'
import { useLocale, useTitle, useVersion } from '../contexts/index.js'
import { useTags } from '../hooks/index.js'
import { getGuides } from '../services/Guides.js'
import { Footer, Octicon } from '../components/index.js'
import config from '../Config.js'
interface Props {
path?: string
}
export function Guides({}: Props) {
const { locale } = useLocale()
const { version, changeVersion } = useVersion()
useTitle(locale('title.guides'))
const [search, setSearch] = useState('')
const [activeTags, toggleTag] = useTags()
const [versionFilter, setVersionFiler] = useState(false)
const versionedGuides = useMemo(() => {
if (versionFilter === false) return getGuides()
return getGuides().filter(guide => {
return guide.versions?.includes(version)
})
}, [version, versionFilter])
const filteredGuides = useMemo(() => {
const query = search.split(' ').map(q => q.trim().toLowerCase()).filter(q => q.length > 0)
return versionedGuides.filter(guide => {
if (!activeTags.every(tag => guide.tags?.includes(tag))) {
return false
}
const content = guide.tags?.join(' ') + ' ' + guide.title.toLowerCase()
return query.every(q => {
if (q.startsWith('!')) {
return q.length === 1 || !content.includes(q.slice(1))
}
return content.includes(q)
})
})
}, [versionedGuides, search, activeTags])
const guides = config.legacyGuides
return <main>
<div class="legacy-container guides">
<div class="navigation">
<TextInput class="btn btn-input query-search" placeholder={locale('guides.search')} value={search} onChange={setSearch} />
<VersionSwitcher value={versionFilter ? version : undefined} onChange={v => {changeVersion(v); setVersionFiler(true)}} hasAny onAny={() => setVersionFiler(false)} />
<div class="tool-card minecraft-wiki">
<img src="https://minecraft.wiki/images/Wiki@2x.png" alt="Minecraft Wiki Logo" />
<div>
The guides have moved to the <em>Minecraft Wiki</em>!
</div>
</div>
{activeTags.length > 0 && <div class="badges-list">
{activeTags.map(tag => <Badge label={tag} onClick={() => toggleTag(tag)} />)}
</div>}
<div class="card-column">
{versionedGuides.length === 0 ? <>
<span class="note">{locale('guides.no_results.version')}</span>
</> : filteredGuides.length === 0 ? <>
<span class="note">{locale('guides.no_results.query')}</span>
</> : filteredGuides.map(g =>
<GuideCard id={g.id} activeTags={activeTags} toggleTag={toggleTag} />
)}
<div class="card-column pt-4">
{guides.map(g => <a class="tool-card" href={`https://minecraft.wiki/w/${g?.link}`} target="_blank">
<div>
<h3>{g.title} {Octicon.link_external}</h3>
</div>
</a>)}
</div>
</div>
<Footer />

View File

@@ -2,7 +2,7 @@ import { useMemo } from 'preact/hooks'
import contributors from '../../contributors.json'
import { Store } from '../Store.js'
import { shuffle } from '../Utils.js'
import { Card, ChangelogEntry, Footer, GeneratorCard, Giscus, GuideCard, ToolCard, ToolGroup } from '../components/index.js'
import { Card, ChangelogEntry, Footer, GeneratorCard, Giscus, ToolCard, ToolGroup } from '../components/index.js'
import { WhatsNewTime } from '../components/whatsnew/WhatsNewTime.jsx'
import { useLocale, useTitle } from '../contexts/index.js'
import { useAsync } from '../hooks/useAsync.js'
@@ -50,7 +50,7 @@ export function Home({}: Props) {
function MinecraftWikiBanner() {
return <a class="tool-card minecraft-wiki" href="https://minecraft.wiki/w/Minecraft_Wiki:Moving_from_Fandom" target="_blank">
<img src="/images/minecraft_wiki.png" alt="Minecraft Wiki Logo" />
<img src="https://minecraft.wiki/images/Wiki@2x.png" alt="Minecraft Wiki Logo" />
<div>
The Minecraft Wiki has moved from Fandom to <em>minecraft.wiki</em>!
</div>
@@ -91,10 +91,7 @@ function FavoriteGenerators() {
function Guides() {
const { locale } = useLocale()
return <ToolGroup title={locale('guides')} link="/guides/" titleIcon="arrow_right">
<GuideCard minimal id="adding-custom-structures" />
<GuideCard minimal id="noise-router" />
</ToolGroup>
return <ToolGroup title={locale('guides')} link="/guides/" titleIcon="arrow_right" />
}
function Tools() {

View File

@@ -1,4 +1,4 @@
import { Footer, GeneratorCard, GeneratorList, GuideCard, ToolGroup } from '../components/index.js'
import { Footer, GeneratorCard, GeneratorList, ToolGroup } from '../components/index.js'
import { useLocale, useTitle } from '../contexts/index.js'
interface Props {
@@ -18,9 +18,13 @@ export function Worldgen({}: Props) {
<GeneratorCard minimal id="worldgen/configured_feature" />
<GeneratorCard minimal id="worldgen/placed_feature" />
</ToolGroup>
<ToolGroup title={locale('guides')} link="/guides/?tags=worldgen" titleIcon="arrow_right">
<GuideCard id="adding-custom-structures" />
<GuideCard id="placed-features" />
<ToolGroup title={locale('guides')} link="/guides/" titleIcon="arrow_right">
<a class="tool-card minecraft-wiki" href="/guides/">
<img src="https://minecraft.wiki/images/Wiki@2x.png" alt="Minecraft Wiki Logo" />
<div>
The guides have moved to the <em>Minecraft Wiki</em>!
</div>
</a>
</ToolGroup>
</div>
<GeneratorList predicate={gen => gen.tags?.includes('worldgen')} />

View File

@@ -1,20 +0,0 @@
export interface Guide {
id: string,
title: string,
versions?: string[],
tags?: string[],
}
declare var __GUIDES__: Guide[]
export function getGuides() {
return __GUIDES__
}
export function getGuide(id: string): Guide {
const guide = getGuides().find(g => g.id === id)
if (guide === undefined) {
return { id, title: 'Unknown Guide' }
}
return guide
}