diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index fb5ba625..13372b3d 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -3,6 +3,8 @@ import starlight from "@astrojs/starlight"; import { generateSchema } from "./src/schema_generator"; +const url = "https://nh.outerwildsmods.com"; + generateSchema("body_schema.json"); generateSchema("star_system_schema.json"); generateSchema("translation_schema.json"); @@ -11,9 +13,25 @@ generateSchema("dialogue_schema.xsd"); generateSchema("text_schema.xsd"); generateSchema("shiplog_schema.xsd"); +const ogMeta = (name, val) => ({ + tag: "meta", + attrs: { + property: `og:${name}`, + content: val + } +}); + +const twMeta = (name, val) => ({ + tag: "meta", + attrs: { + name: `twitter:${name}`, + content: val + } +}); + // https://astro.build/config export default defineConfig({ - site: "https://nh.outerwildsmods.com", + site: url, compressHTML: true, integrations: [ starlight({ @@ -21,6 +39,7 @@ export default defineConfig({ description: "Documentation on how to use the New Horizons planet creation tool for Outer Wilds.", defaultLocale: "en-us", + favicon: "/favicon.png", components: { PageSidebar: "/src/components/ConditionalPageSidebar.astro" }, @@ -33,6 +52,14 @@ export default defineConfig({ github: "https://github.com/Outer-Wilds-New-Horizons/new-horizons", discord: "https://discord.gg/wusTQYbYTc" }, + head: [ + ogMeta("image", `${url}/og_image.webp`), + ogMeta("image:width", "1200"), + ogMeta("image:height", "400"), + twMeta("card", "summary"), + twMeta("image", `${url}/og_image.webp`), + { tag: "meta", attrs: { name: "theme-color", content: "#ffab8a" } } + ], sidebar: [ { label: "Start Here", diff --git a/docs/public/favicon.ico b/docs/public/favicon.ico deleted file mode 100644 index a943dc7b..00000000 Binary files a/docs/public/favicon.ico and /dev/null differ diff --git a/docs/public/favicon.png b/docs/public/favicon.png new file mode 100644 index 00000000..d0db66b1 Binary files /dev/null and b/docs/public/favicon.png differ diff --git a/docs/public/favicon.svg b/docs/public/favicon.svg deleted file mode 100644 index cba5ac14..00000000 --- a/docs/public/favicon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/public/og_image.webp b/docs/public/og_image.webp new file mode 100644 index 00000000..20f248b9 Binary files /dev/null and b/docs/public/og_image.webp differ diff --git a/docs/src/components/ConditionalPageSidebar.astro b/docs/src/components/ConditionalPageSidebar.astro index 1db046db..89d83691 100644 --- a/docs/src/components/ConditionalPageSidebar.astro +++ b/docs/src/components/ConditionalPageSidebar.astro @@ -4,7 +4,7 @@ import Default from "@astrojs/starlight/components/PageSidebar.astro"; import { SchemaTools } from "../schema_utils"; import type { MarkdownHeading } from "astro"; -const isSchema = Astro.props.slug.startsWith("schemas/"); +const isSchema = Astro.props.slug.startsWith("schemas/") && !Astro.props.slug.endsWith("/defs"); type TocItem = Exclude["items"]["find"]>, undefined>; @@ -29,15 +29,17 @@ function generateToC( let props = Astro.props; if (isSchema) { - console.log("Is Schema!"); const schemaFileName = props.entry.data.head[0]?.attrs?.fileName as string | undefined; if (schemaFileName) { - const schema = SchemaTools.readSchema(schemaFileName); + let schema = SchemaTools.readSchema(schemaFileName); + const defName = props.entry.data.head[0]?.attrs?.def as string | undefined; + if (defName) { + schema = SchemaTools.getDefs(schema).find(d => d.slug === defName)!; + } const headings = SchemaTools.getHeaders(schema); props.headings = headings; props.toc!.items = generateToC(headings, props.entry.data.title); } - console.log(props.toc); } --- diff --git a/docs/src/components/Schemas/Content.astro b/docs/src/components/Schemas/Content.astro index 4a43cae2..40b60f75 100644 --- a/docs/src/components/Schemas/Content.astro +++ b/docs/src/components/Schemas/Content.astro @@ -1,5 +1,6 @@ --- -import { Schema, SchemaTools } from '../../schema_utils'; +import { SchemaTools } from "../../schema_utils"; +import type { Schema } from "../../schema_utils"; export interface Props { schema: Schema; @@ -19,20 +20,25 @@ const type = SchemaTools.getType(schema); const link = `https://raw.githubusercontent.com/Outer-Wilds-New-Horizons/new-horizons/main/NewHorizons/Schemas/${schema.fileName}`; const refSlug = SchemaTools.getRefSlug(schema); const enumVals = SchemaTools.getEnumValues(schema); -const props = SchemaTools.getProps(schema); +const props = SchemaTools.getProps(schema, level); const HeadingTag = levelMap[level] ?? "h6"; ---
- { - level !== 0 && ( - - {SchemaTools.getTitle(schema)} - - ) - } + { + level !== 0 && ( + + {level !== 0 && ( + + )} + {SchemaTools.getTitle(schema)} + + ) + }
{level === 0 && Schema Type: {schema.internalSchema.type}} { @@ -47,15 +53,10 @@ const HeadingTag = levelMap[level] ?? "h6"; { level === 0 && !isDef && ( ) } @@ -76,7 +77,9 @@ const HeadingTag = levelMap[level] ?? "h6"; } { refSlug && ( - See Definitions/{refSlug} + + See Definitions/{refSlug} + ) } { @@ -99,7 +102,7 @@ const HeadingTag = levelMap[level] ?? "h6"; color: unset; } 50% { - color: var(--sl-theme-accent); + color: var(--sl-color-accent); } 100% { color: unset; @@ -107,14 +110,29 @@ const HeadingTag = levelMap[level] ?? "h6"; } .title:target { - transition: color; animation: flash 600ms cubic-bezier(0.45, 0.05, 0.55, 0.95) 3; } + .title:hover a.anchor { + display: initial; + } + + a.anchor { + text-decoration: none; + float: left; + margin-left: -26px; + padding-right: 5px; + display: none; + } + + a.anchor:hover { + display: initial; + color: var(--sl-color-accent); + } + div.header { display: flex; flex-direction: column; - gap: 1rem; } div.wrapper[data-level="2"] { @@ -133,35 +151,33 @@ const HeadingTag = levelMap[level] ?? "h6"; box-sizing: border-box; display: flex; flex-direction: column; - gap: 2rem; } div.children { display: flex; flex-direction: column; - gap: 2rem; } div.tool-links { display: flex; - gap: 1rem; - } - - ul { - margin-top: 0.5rem; } span { - background-color: hsl(var(--sl-hue-accent) 50% 10%); + background-color: var(--sl-color-accent-low); font-size: small; padding: 0.5rem; - margin-right: 0.3rem; - border: solid 2px var(--sl-color-accent-low); + border: solid 2px var(--sl-color-accent); border-radius: 5rem; } span.required { - background-color: hsl(var(--sl-hue-yellow) 50% 10%); - border-color: var(--sl-color-yellow-low); + --hue-yellow: 53; + background-color: hsl(var(--hue-yellow) 50% 20%); + border-color: hsl(var(--hue-yellow) 50% 50%); + } + + :root[data-theme="light"] span.required { + background-color: yellow; + border-color: darkgoldenrod; } diff --git a/docs/src/components/Schemas/DefinitionList.astro b/docs/src/components/Schemas/DefinitionList.astro new file mode 100644 index 00000000..78e32298 --- /dev/null +++ b/docs/src/components/Schemas/DefinitionList.astro @@ -0,0 +1,21 @@ +--- +import { SchemaTools } from '../../schema_utils'; +import Breadcrumb from './Breadcrumb.astro'; + +interface Props { + fileName: string; +} + +const { fileName } = Astro.props; + +const schema = SchemaTools.readSchema(fileName); + +const defs = SchemaTools.getDefs(schema); + +--- + + + + diff --git a/docs/src/components/Schemas/SchemaDef.astro b/docs/src/components/Schemas/SchemaDef.astro index 247a2b68..e446bbec 100644 --- a/docs/src/components/Schemas/SchemaDef.astro +++ b/docs/src/components/Schemas/SchemaDef.astro @@ -1,5 +1,6 @@ --- import { SchemaTools } from '../../schema_utils'; +import Breadcrumb from './Breadcrumb.astro'; import Content from './Content.astro'; interface Props { @@ -9,12 +10,13 @@ interface Props { const { fileName, def } = Astro.props; -const schema = SchemaTools.readSchema(`../NewHorizons/Schemas/${fileName}`); +const schema = SchemaTools.readSchema(fileName); const defs = SchemaTools.getDefs(schema); const targetDef = defs.find(d => d.slug === def); --- + diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index 27a5b3f6..d13884f3 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -13,7 +13,7 @@ hero: icon: right-arrow variant: primary - text: Schema Reference - link: /schemas/body_schema + link: /schemas/body-schema --- import { Card, CardGrid } from "@astrojs/starlight/components"; diff --git a/docs/src/content/docs/start-here/getting-started.md b/docs/src/content/docs/start-here/getting-started.md index d3606fb5..e1c6e571 100644 --- a/docs/src/content/docs/start-here/getting-started.md +++ b/docs/src/content/docs/start-here/getting-started.md @@ -96,7 +96,7 @@ With the schema you get: - Automatic error detection for incorrect data types or values - Autocomplete, also called IntelliSense -The schema we're using here is the [Celestial Body Schema](/schemas/body_schema), but there are many others available in the Schemas section of the left sidebar. +The schema we're using here is the [Celestial Body Schema](/schemas/body-schema), but there are many others available in the Schemas section of the left sidebar. ### Testing The Planet diff --git a/docs/src/schema_generator.ts b/docs/src/schema_generator.ts index 5ffb84da..6c3141d6 100644 --- a/docs/src/schema_generator.ts +++ b/docs/src/schema_generator.ts @@ -1,4 +1,4 @@ -import { SchemaTools } from "./schema_utils"; +import { SchemaTools, type Schema } from "./schema_utils"; import * as fs from "node:fs"; const addFrontmatter = ( @@ -14,13 +14,58 @@ const addFrontmatter = ( return `---\n${entries.join("\n")}\n---\n\n${content}`; }; +const generateDef = (def: Schema) => { + const title = SchemaTools.getTitle(def) as string; + const dir = `src/content/docs/schemas/${def.rootSlug!}/defs/${title}`; + + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + + let description = SchemaTools.getDescription(def) as string | undefined; + + if (description === undefined || (description as string).trim() === "") { + description = `Definition of ${title}`; + } + + const frontMatter = { + title, + description, + editUrl: false, + head: `\n - tag: meta\n attrs:\n fileName: ${def.fileName}\n def: ${title}` + }; + + const content = `import SchemaDef from "/src/components/Schemas/SchemaDef.astro";\n\n\n`; + + fs.writeFileSync(`${dir}/index.mdx`, addFrontmatter(content, frontMatter)); +}; + +const generateDefList = (schema: Schema) => { + const dir = `src/content/docs/schemas/${schema.slug}/defs`; + + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + + const frontMatter = { + title: `${SchemaTools.getTitle(schema)} definitions`, + description: "List of all definitions in the ${SchemaTools.getTitle(schema)} schema", + editUrl: false, + head: `\n - tag: meta\n attrs:\n fileName: ${schema.fileName}` + }; + + const content = `import DefinitionList from "/src/components/Schemas/DefinitionList.astro";\n\n\n`; + + fs.writeFileSync(`${dir}/index.mdx`, addFrontmatter(content, frontMatter)); +}; + export const generateSchema = (fileName: string) => { const schema = SchemaTools.readSchema(fileName); const dir = `src/content/docs/schemas/${schema.slug}`; if (!fs.existsSync(dir)) { - fs.mkdirSync(dir); + fs.mkdirSync(dir, { recursive: true }); } const frontMatter = { @@ -33,4 +78,10 @@ export const generateSchema = (fileName: string) => { const content = `import Schema from "/src/components/Schemas/Schema.astro";\n\n\n`; fs.writeFileSync(`${dir}/index.mdx`, addFrontmatter(content, frontMatter)); + + generateDefList(schema); + + for (const def of SchemaTools.getDefs(schema)) { + generateDef(def); + } }; diff --git a/docs/src/schema_utils.ts b/docs/src/schema_utils.ts index 156493c7..20239592 100644 --- a/docs/src/schema_utils.ts +++ b/docs/src/schema_utils.ts @@ -85,6 +85,7 @@ export const SchemaTools = { return documentation.elements?.[0]?.text; } } + def: string; } }, @@ -222,7 +223,7 @@ export const SchemaTools = { } }, - getProps: (schema: Schema): [string, Schema][] => { + getProps: (schema: Schema, level: number): [string, Schema][] => { switch (schema.internalSchema.type) { case "JSON": const internalSchema = schema.internalSchema.val; @@ -231,7 +232,7 @@ export const SchemaTools = { e[0], { fileName: schema.fileName, - slug: `${schema.slug}-${getSchemaSlug(e[0])}`, + slug: `${level === 0 ? "" : `${schema.slug}-`}${getSchemaSlug(e[0])}`, rootSlug: schema.rootSlug, internalSchema: { type: "JSON", @@ -245,7 +246,7 @@ export const SchemaTools = { "Items", { fileName: schema.fileName, - slug: `${schema.slug}-items`, + slug: `${level === 0 ? "" : `${schema.slug}-`}items`, rootSlug: schema.rootSlug, internalSchema: { type: "JSON", diff --git a/docs/src/styles/custom.css b/docs/src/styles/custom.css index 02143adf..b25ed43b 100644 --- a/docs/src/styles/custom.css +++ b/docs/src/styles/custom.css @@ -12,6 +12,7 @@ --sl-color-gray-6: #272727; --sl-color-black: #181818; } + /* Light mode colors. */ :root[data-theme="light"] { --sl-color-accent-low: #b8e4c0;