Improve version and article linking

This commit is contained in:
Misode
2022-05-12 16:58:10 +02:00
parent ad13cc131b
commit e2bcf2d1a7
7 changed files with 90 additions and 62 deletions

View File

@@ -11,16 +11,18 @@ export function Giscus({ term }: Props) {
? `http://localhost:3000/src/styles/giscus${themeSuffix}.css`
: `${location.protocol}//${location.host}/assets/giscus${themeSuffix}.css`
return <GiscusReact
repo="misode/misode.github.io"
repoId="MDEwOlJlcG9zaXRvcnkxOTIyNTQyMzA="
category="Site"
categoryId="DIC_kwDOC3WRFs4COB8r"
mapping={term ? 'specific' : 'pathname'}
term={term}
reactionsEnabled="1"
emitMetadata="0"
inputPosition="top"
theme={themeUrl}
lang="en" />
return <div class="giscus-container">
<GiscusReact
repo="misode/misode.github.io"
repoId="MDEwOlJlcG9zaXRvcnkxOTIyNTQyMzA="
category="Site"
categoryId="DIC_kwDOC3WRFs4COB8r"
mapping={term ? 'specific' : 'pathname'}
term={term}
reactionsEnabled="1"
emitMetadata="0"
inputPosition="top"
theme={themeUrl}
lang="en" />
</div>
}

View File

@@ -1,6 +1,6 @@
import { marked } from 'marked'
import { ChangelogTag } from '.'
import type { Change, ChangelogVersion } from '../../services'
import type { Change } from '../../services'
type Props = {
change: Change,
@@ -10,8 +10,8 @@ type Props = {
export function ChangelogEntry({ change, activeTags, toggleTag }: Props) {
return <div class="changelog-entry">
<div class="changelog-version">
<ArticleLink {...change.version}/>
<ArticleLink {...change.group}/>
<a href={`/versions/?id=${change.version}`}>{change.version}</a>
<a href={`/versions/?id=${change.group}`}>{change.group}</a>
</div>
<div class="changelog-tags">
{change.tags.map(tag => <ChangelogTag label={tag} onClick={toggleTag ? () => toggleTag(tag) : undefined} active={activeTags?.includes(tag)} />)}
@@ -19,9 +19,3 @@ export function ChangelogEntry({ change, activeTags, toggleTag }: Props) {
<div class="changelog-content" dangerouslySetInnerHTML={{ __html: marked(change.content) }} />
</div>
}
function ArticleLink({ id, article }: ChangelogVersion) {
return article === null
? <span>{id}</span>
: <a href={`https://www.minecraft.net/en-us/article/${article}`} target="_blank">{id}</a>
}

View File

@@ -2,16 +2,18 @@ import { useEffect, useMemo, useState } from 'preact/hooks'
import { VersionMetaData } from '.'
import { useLocale } from '../../contexts'
import type { Change, VersionMeta } from '../../services'
import { getChangelogs } from '../../services'
import { getArticleLink, getChangelogs } from '../../services'
import { Giscus } from '../Giscus'
import { Octicon } from '../Octicon'
import { ChangelogList } from './ChangelogList'
type Tab = 'changelog' | 'discussion'
interface Props {
version: VersionMeta
id: string,
version?: VersionMeta,
}
export function VersionDetail({ version }: Props) {
export function VersionDetail({ id, version }: Props) {
const { locale } = useLocale()
const [tab, setTab] = useState<Tab>('changelog')
@@ -20,33 +22,45 @@ export function VersionDetail({ version }: Props) {
useEffect(() => {
getChangelogs()
.then(changelogs => setChangelogs(
changelogs.map(c => ({ ...c, tags: c.tags.filter(t => t !== c.group.id) }))
changelogs.map(c => ({ ...c, tags: c.tags.filter(t => t !== c.group) }))
))
.catch(e => console.error(e))
}, [])
const filteredChangelogs = useMemo(() =>
changelogs?.filter(c => c.version.id === version.id || c.group.id === version.id),
[version.id, changelogs])
changelogs?.filter(c => c.version === id || c.group === id),
[id, changelogs])
const articleLink = version && getArticleLink(version.id)
return <>
<div class="version-detail">
<h2>{version.name}</h2>
<h2>{version?.name ?? id}</h2>
<div class="version-info">
<VersionMetaData label={locale('versions.released')} value={releaseDate(version)} />
<VersionMetaData label={locale('versions.release_target')} value={version.release_target} link={version.id !== version.release_target ? `/versions/?id=${version.release_target}` : undefined} />
<VersionMetaData label={locale('versions.data_version')} value={version.data_version} />
<VersionMetaData label={locale('versions.protocol_version')} value={version.protocol_version} />
<VersionMetaData label={locale('versions.data_pack_format')} value={version.data_pack_version} />
<VersionMetaData label={locale('versions.resource_pack_format')} value={version.resource_pack_version} />
{version ? <>
<VersionMetaData label={locale('versions.released')} value={releaseDate(version)} />
<VersionMetaData label={locale('versions.release_target')} value={version.release_target} link={version.id !== version.release_target ? `/versions/?id=${version.release_target}` : undefined} />
<VersionMetaData label={locale('versions.data_version')} value={version.data_version} />
<VersionMetaData label={locale('versions.protocol_version')} value={version.protocol_version} />
<VersionMetaData label={locale('versions.data_pack_format')} value={version.data_pack_version} />
<VersionMetaData label={locale('versions.resource_pack_format')} value={version.resource_pack_version} />
</> : filteredChangelogs?.length ?? 0 > 1 ? <p>
This version is not released yet.
</p> : <p>
This version does not exist. Only versions since 1.14 are tracked, or it may be too recent.
</p>}
</div>
<div class="version-tabs">
<span class={tab === 'changelog' ? 'selected' : ''} onClick={() => setTab('changelog')}>{locale('versions.technical_changes')}</span>
<span class={tab === 'discussion' ? 'selected' : ''} onClick={() => setTab('discussion')}>{locale('versions.discussion')}</span>
{articleLink && <a href={articleLink} target="_blank">
{locale('versions.article')}
{Octicon.link_external}
</a>}
</div>
<div class="version-tab">
{tab === 'changelog' && <ChangelogList changes={filteredChangelogs} defaultOrder="asc" />}
{tab === 'discussion' && <Giscus term={`version/${version.id}`} />}
{tab === 'discussion' && <Giscus term={`version/${id}/`} />}
</div>
</div>
</>

View File

@@ -43,13 +43,7 @@ export function Versions({}: Props) {
{Octicon.arrow_right}
</a>
</div>
{selected ? <VersionDetail version={selected} />
: <div class="version-detail">
<h2>{selectedId}</h2>
<div class="version-info">
<p>This version does not exist. Only versions since 1.14 are tracked, or it may be too recent.</p>
</div>
</div>}
<VersionDetail id={selectedId} version={selected} />
</> : <VersionList versions={versions ?? []} link={id => `/versions/?id=${id}`} />}
</div>
</main>

View File

@@ -3,18 +3,13 @@ import { isObject } from '../Utils'
const repo = 'https://raw.githubusercontent.com/misode/technical-changes/main'
export type Change = {
group: ChangelogVersion,
version: ChangelogVersion,
group: string,
version: string,
order: number,
tags: string[],
content: string,
}
export type ChangelogVersion = {
id: string,
article: string | null,
}
let Changelogs: Change[] | Promise<Change[]> | null = null
export async function getChangelogs() {
@@ -24,21 +19,21 @@ export async function getChangelogs() {
index.map((group, i) => fetchGroup(parseVersion(group), i))
)).flat().map<Change>(change => ({
...change,
tags: [change.group.id, ...change.tags],
tags: [change.group, ...change.tags],
}))
}
return Changelogs
}
async function fetchGroup(group: ChangelogVersion, groupIndex: number) {
const index = await (await fetch(`${repo}/${group.id}/index.json`)).json() as string[]
async function fetchGroup(group: string, groupIndex: number) {
const index = await (await fetch(`${repo}/${group}/index.json`)).json() as string[]
return (await Promise.all(
index.map((version, i) => fetchChangelog(group, parseVersion(version), groupIndex, i))
)).flat()
}
async function fetchChangelog(group: ChangelogVersion, version: ChangelogVersion, groupIndex: number, versionIndex: number) {
const text = await (await fetch(`${repo}/${group.id}/${version.id}.md`)).text()
async function fetchChangelog(group: string, version: string, groupIndex: number, versionIndex: number) {
const text = await (await fetch(`${repo}/${group}/${version}.md`)).text()
return parseChangelog(text).map(change => ({
version,
group,
@@ -60,14 +55,32 @@ function parseChangelog(text: string) {
})
}
function parseVersion(version: unknown): ChangelogVersion {
function parseVersion(version: unknown): string {
if (typeof version === 'string') {
return {
id: version,
article: version.match(/\d\dw\d\d[a-z]/) ? 'minecraft-snapshot-' + version : version.match(/\d+\.\d+(\.\d+)?-pre[0-9]+/) ? 'minecraft-' + version.replaceAll('.', '-').replaceAll('pre', 'pre-release-') : null,
}
return version
} else if (isObject(version)) {
return version as ChangelogVersion
return version.id
}
return { id: 'unknown', article: null }
return 'unknown'
}
const ARTICLE_PREFIX = 'https://www.minecraft.net/article/'
const ARTICLE_OVERRIDES = new Map(Object.entries({
1.17: 'caves---cliffs--part-i-out-today-java',
1.18: 'caves---cliffs--part-ii-out-today-java',
'1.18.2': 'minecraft-java-edition-1-18-2',
}))
export function getArticleLink(version: string): string | undefined {
const override = ARTICLE_OVERRIDES.get(version)
if (override) {
return ARTICLE_PREFIX + override
}
if (version.match(/^\d\dw\d\d[a-z]$/)) {
return ARTICLE_PREFIX + 'minecraft-snapshot-' + version
}
if (version.match(/^\d+\.\d+(\.\d+)?-(pre|rc)[0-9]+$/)) {
return ARTICLE_PREFIX + 'minecraft-' + version.replaceAll('.', '-').replaceAll('pre', 'pre-release-')
}
return undefined
}

View File

@@ -130,6 +130,7 @@
"terrain_settings": "Terrain settings",
"text_component": "Text Component",
"undo": "Undo",
"versions.article": "Article",
"versions.search": "Search versions",
"versions.no_results": "No results",
"versions.all": "All versions",

View File

@@ -1446,6 +1446,15 @@ hr {
border-bottom: 2px solid transparent;
padding: 8px 16px;
cursor: pointer;
color: var(--text-3);
fill: var(--text-3);
text-decoration: none;
display: inline-flex;
align-items: center;
}
.version-tabs > * > svg {
margin-left: 8px;
}
.version-tabs > .selected {
@@ -1496,8 +1505,9 @@ hr {
background-color: var(--selection) !important;
}
.giscus {
.giscus-container {
margin-top: 16px;
min-height: 325.667px;
}
.guide-card {